/* Northrift Wealth demo — layout, display modes and demo shell, v1.0.0
 * Colour, type, radius and elevation live in tokens.css and stay inline on the
 * elements exactly as the prototype had them. Only *layout* moved into classes,
 * so that web-mobile and native-app can override it without !important.
 * Desktop values are byte-identical to the source prototype.
 */

/* ========================================================================== */
/* App layout — web-desktop is the prototype's own geometry                    */
/* ========================================================================== */

.nr-app { min-height: 100vh; background: var(--canvas); color: var(--text-strong); }

.nr-topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-24); height: 56px; padding: 0 var(--sp-24);
  position: sticky; top: 0; z-index: 60;
}
.nr-workspace {
  display: grid; grid-template-columns: 240px minmax(0, 1fr);
  min-height: calc(100vh - 56px);
}
.nr-side {
  padding: var(--sp-22) var(--sp-14);
  display: flex; flex-direction: column; gap: var(--sp-20);
  position: sticky; top: 56px; align-self: start; height: calc(100vh - 56px);
}
.nr-main { padding: var(--sp-30) var(--sp-40) var(--sp-76); min-width: 0; }
.nr-page { max-width: var(--pw, 1180px); }
.nr-col { display: flex; flex-direction: column; gap: var(--gap, var(--sp-20)); min-width: 0; }
.nr-grid {
  display: grid; grid-template-columns: var(--gt);
  gap: var(--gap, var(--sp-20)); align-items: var(--ai, start); min-width: 0;
}
.nr-cards { display: grid; grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr)); gap: var(--gap, var(--sp-12)); }
.nr-autofit { display: grid; grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); gap: var(--sp-12); }
.nr-tgrid { display: grid; grid-template-columns: var(--tg); gap: var(--sp-12); align-items: center; }
.nr-week7 { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--gap, var(--sp-8)); }
.nr-headrow { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-20); flex-wrap: wrap; }
.nr-kpis { display: flex; gap: var(--sp-28); }
.nr-bottomnav { display: none; }
.nr-native-only { display: none; }

/* pressable feedback for every control the app renders.
 * min-height lives here rather than in the inline styles so the narrow versions
 * can raise every target to 44px — an inline style could not be overridden. */
.nr-press { min-height: 32px; transition: transform var(--d-fast) var(--ease), box-shadow var(--d-fast) var(--ease), background var(--d-fast) var(--ease); }
.nr-press:active { transform: translateY(1px); }
.nr-press[disabled], .nr-press[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; transform: none; }
.nr-hov-soft:hover { background: var(--surface-soft); }
.nr-hov-mute:hover { background: var(--surface-muted); }
.nr-hov-lift:hover { box-shadow: var(--shadow-2); transform: translateY(-1px); }
.nr-hov-accent:hover { background: var(--accent-link-hover); }

/* ========================================================================== */
/* web-mobile — same adaptive web layout, narrow                              */
/* ========================================================================== */

:root[data-mode="web-mobile"] .nr-workspace { display: block; min-height: calc(100vh - 56px); }
:root[data-mode="web-mobile"] .nr-side { display: none; }
:root[data-mode="web-mobile"] .nr-main { padding: var(--sp-18) var(--sp-16) 96px; }
:root[data-mode="web-mobile"] .nr-page { max-width: none; }
:root[data-mode="web-mobile"] .nr-grid,
:root[data-mode="web-mobile"] .nr-cards { grid-template-columns: minmax(0, 1fr); }
:root[data-mode="web-mobile"] .nr-kpis { flex-wrap: wrap; gap: var(--sp-16) var(--sp-20); }
:root[data-mode="web-mobile"] .nr-headrow { align-items: flex-start; gap: var(--sp-12); }
:root[data-mode="web-mobile"] .nr-topbar { padding: 0 var(--sp-14); gap: var(--sp-10); }
:root[data-mode="web-mobile"] .nr-bottomnav {
  display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
  gap: var(--sp-2); padding: var(--sp-8) var(--sp-8) calc(var(--sp-8) + env(safe-area-inset-bottom, 0px));
  background: var(--tabbar-bg); border-top: 1px solid var(--border);
  backdrop-filter: blur(14px);
}
:root[data-mode="web-mobile"] .nr-bottomnav > button { flex: 1; min-width: 0; min-height: 44px; }
:root[data-mode="web-mobile"] .nr-desktop-only { display: none; }

/* ========================================================================== */
/* native-app — mobile-app idiom, framed where there is room                  */
/* ========================================================================== */

:root[data-mode="native-app"] .nr-workspace { display: block; min-height: 0; }
:root[data-mode="native-app"] .nr-side,
:root[data-mode="native-app"] .nr-topbar { display: none; }
:root[data-mode="native-app"] .nr-main { padding: 0 0 104px; }
:root[data-mode="native-app"] .nr-page { max-width: none; }
:root[data-mode="native-app"] .nr-grid,
:root[data-mode="native-app"] .nr-cards { grid-template-columns: minmax(0, 1fr); }
:root[data-mode="native-app"] .nr-kpis { flex-wrap: wrap; gap: var(--sp-14) var(--sp-20); }
:root[data-mode="native-app"] .nr-desktop-only { display: none; }
:root[data-mode="native-app"] .nr-native-only { display: block; }
:root[data-mode="native-app"] .nr-hov-soft:hover,
:root[data-mode="native-app"] .nr-hov-lift:hover { background: inherit; box-shadow: var(--shadow-1); transform: none; }
:root[data-mode="native-app"] .nr-press:active { transform: scale(0.985); opacity: 0.9; }

.nr-status-bar {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-12) var(--sp-26) var(--sp-4); flex: none;
}
.nr-native-head { padding: var(--sp-10) var(--sp-20) var(--sp-8); }
.nr-native-body { padding: 0 var(--sp-20); display: flex; flex-direction: column; gap: var(--sp-14); }
/* The tab bar sits inside the canvas, which the frame has already inset by its
 * own padding — so it goes edge to edge here, or content shows below it. */
.nr-tabbar {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: var(--tabbar-bg); backdrop-filter: blur(14px);
  border-top: 1px solid var(--border); border-radius: 0 0 var(--r-38) var(--r-38);
  padding: var(--sp-8) var(--sp-10) var(--sp-16); display: flex; gap: var(--sp-2);
}
.nr-tabbar > button { flex: 1; min-width: 0; min-height: 44px; }
/* unframed native (a real phone): the tab bar is fixed to the viewport */
:root[data-mode="native-app"][data-framed="false"] .nr-tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; border-radius: 0;
  padding-bottom: calc(var(--sp-14) + env(safe-area-inset-bottom, 0px));
}

/* ========================================================================== */
/* Demo shell — the surface that belongs to the demo, not to the product      */
/* ========================================================================== */

.demo-shell { min-height: 100vh; display: flex; flex-direction: column; background: var(--canvas); }
.demo-bar {
  display: flex; align-items: center; gap: var(--sp-10); flex-wrap: wrap;
  padding: var(--sp-8) var(--sp-16); background: var(--surface);
  border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 80;
}
.demo-brand { display: flex; align-items: center; gap: var(--sp-8); margin-right: var(--sp-4); }
.demo-bar-spacer { flex: 1 1 auto; }
.demo-group { display: flex; gap: var(--sp-4); padding: var(--sp-4); background: var(--surface-muted); border-radius: var(--r-pill); }
.demo-btn {
  border: 0; cursor: pointer; background: var(--surface-muted); color: var(--text);
  font: 600 var(--fs-12) var(--font-sans); padding: var(--sp-8) var(--sp-12);
  border-radius: var(--r-10); min-height: 34px;
}
.demo-btn:hover { background: var(--border); }
.demo-btn[aria-pressed="true"] { background: var(--ink); color: var(--text-on-ink); }
.demo-seg {
  border: 0; cursor: pointer; background: transparent; color: var(--text-muted);
  font: 600 var(--fs-12) var(--font-sans); padding: var(--sp-7) var(--sp-12);
  border-radius: var(--r-pill); min-height: 32px; white-space: nowrap;
}
.demo-seg[aria-pressed="true"] { background: var(--surface); color: var(--text-strong); box-shadow: var(--shadow-1); }
.demo-chip {
  display: inline-flex; align-items: center; gap: var(--sp-6);
  background: var(--mint); color: var(--on-mint);
  font: 700 var(--fs-11) var(--font-sans); letter-spacing: 0.06em; text-transform: uppercase;
  padding: var(--sp-6) var(--sp-11); border-radius: var(--r-pill);
}
.demo-chip > span:first-child { width: 7px; height: 7px; border-radius: var(--r-pill); background: var(--teal); }
.demo-stage { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* device frame — only when there is room around it */
.demo-stage--framed {
  align-items: center; justify-content: flex-start;
  padding: var(--sp-32) var(--sp-20) var(--sp-48); background: var(--canvas);
}
.demo-frame {
  width: 390px; height: min(800px, calc(100vh - 190px)); min-height: 620px;
  background: var(--ink); border-radius: var(--r-46); padding: var(--sp-10);
  box-shadow: var(--shadow-frame); position: relative; flex: none;
}
.demo-canvas {
  width: 100%; height: 100%; background: var(--surface-soft);
  border-radius: var(--r-38); overflow: hidden; position: relative;
  display: flex; flex-direction: column;
}
.demo-canvas-scroll { flex: 1; overflow-y: auto; padding: var(--sp-10) 0 104px; }
.demo-stage--plain .demo-canvas { border-radius: 0; height: auto; min-height: calc(100vh - 52px); }
.demo-stage--plain .demo-canvas-scroll { padding-bottom: 104px; }
.demo-frame-side { display: flex; align-items: flex-start; gap: var(--sp-24); }
.demo-frame-aside { width: 300px; flex: none; display: flex; flex-direction: column; gap: var(--sp-12); padding-top: var(--sp-40); }
@media (max-width: 1100px) { .demo-frame-aside { display: none; } }

/* ========================================================================== */
/* Guided Mode — always outside the application surface                       */
/* ========================================================================== */

.guide {
  background: var(--surface); border: 1px solid var(--accent);
  border-radius: var(--r-16); box-shadow: var(--shadow-2);
  padding: var(--sp-14) var(--sp-16); max-width: 320px; z-index: 88;
}
.guide-kicker { font: 700 var(--fs-10) var(--font-sans); letter-spacing: 0.12em; text-transform: uppercase; color: var(--teal); }
.guide-title { font: 700 var(--fs-14) var(--font-sans); color: var(--text-strong); margin-top: var(--sp-5); }
.guide-body { font: 400 var(--fs-13)/18px var(--font-sans); color: var(--text); margin-top: var(--sp-6); text-wrap: pretty; }
.guide-next { font: 600 var(--fs-12) var(--font-sans); color: var(--teal); margin-top: var(--sp-8); }
.guide-close {
  position: absolute; top: var(--sp-8); right: var(--sp-8);
  width: 26px; height: 26px; min-width: 26px; border: 0; cursor: pointer;
  border-radius: var(--r-pill); background: var(--surface-muted); color: var(--text);
  font: 400 var(--fs-13) var(--font-sans);
}
/* Both shell surfaces that live in the corner — the guided bubble and the
 * emulated channel — share one stack, so they can never cover each other. */
.demo-corner {
  position: fixed; right: var(--sp-24); bottom: var(--sp-24); z-index: 92;
  display: flex; flex-direction: column; gap: var(--sp-12); align-items: flex-end;
  max-width: min(360px, calc(100vw - 32px)); pointer-events: none;
}
.demo-corner > * { pointer-events: auto; }
.demo-corner > .guide, .demo-corner > .channel {
  position: relative; right: auto; bottom: auto; left: auto; width: 320px; max-width: 100%;
}
.guide--float { position: fixed; right: var(--sp-24); bottom: var(--sp-24); }
.guide--mobile {
  position: fixed; left: var(--sp-12); right: var(--sp-12); bottom: 84px;
  max-width: none; max-height: 30vh; overflow-y: auto;
}
/* compact on a phone: never more than a third of the screen (§12.2) */
:root[data-mode="web-mobile"] .demo-corner > .guide,
:root[data-mode="native-app"][data-framed="false"] .demo-corner > .guide {
  padding: var(--sp-12) var(--sp-13); max-height: 30vh; overflow-y: auto;
}
:root[data-mode="web-mobile"] .guide-body { font: 400 var(--fs-12)/17px var(--font-sans); }
:root[data-mode="web-mobile"] .guide-title { font: 700 var(--fs-13) var(--font-sans); }
:root[data-mode="web-mobile"] .demo-corner,
:root[data-mode="native-app"][data-framed="false"] .demo-corner {
  left: var(--sp-12); right: var(--sp-12); bottom: 84px; align-items: stretch; max-width: none;
}
:root[data-mode="web-mobile"] .demo-corner > .guide { max-height: 33vh; overflow-y: auto; }
:root[data-mode="web-mobile"] .demo-corner > .guide,
:root[data-mode="web-mobile"] .demo-corner > .channel,
:root[data-mode="native-app"][data-framed="false"] .demo-corner > .channel { width: auto; }
.guide--aside { position: relative; max-width: 300px; }
.guide-anchor-line { height: 1px; background: var(--accent); flex: 1; align-self: center; }

/* ========================================================================== */
/* Emulated external channels — drawn inside the demo, never system UI        */
/* ========================================================================== */

.channel {
  position: fixed; right: var(--sp-24); bottom: var(--sp-24); width: 320px; z-index: 92;
  background: var(--surface); border-radius: var(--r-20); box-shadow: var(--shadow-2);
  border: 1px solid var(--border); overflow: hidden;
}
.channel-head {
  display: flex; align-items: center; gap: var(--sp-8);
  padding: var(--sp-10) var(--sp-14); background: var(--surface-muted);
  border-bottom: 1px solid var(--border);
}
.channel-body { padding: var(--sp-14); }
.channel-demo-tag {
  font: 700 var(--fs-9) var(--font-sans); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--teal); background: var(--mint); padding: 3px var(--sp-6); border-radius: var(--r-6);
}
@media (max-width: 720px) {
  .channel { left: var(--sp-12); right: var(--sp-12); width: auto; bottom: 96px; }
}

.demo-toast {
  position: fixed; bottom: var(--sp-24); left: 50%; transform: translateX(-50%);
  background: var(--ink); color: var(--text-on-ink);
  font: 600 var(--fs-13) var(--font-sans); padding: var(--sp-13) var(--sp-20);
  border-radius: var(--r-pill); z-index: 95;
  max-width: calc(100vw - 32px); text-align: center;
}

/* ========================================================================== */
/* Modals (web) and sheets (native)                                           */
/* ========================================================================== */

.nr-modal {
  position: fixed; inset: 0; background: var(--overlay); z-index: 90;
  display: flex; align-items: center; justify-content: center; padding: var(--sp-40);
}
.nr-modal-card {
  background: var(--surface); border-radius: var(--r-24);
  width: var(--mw, 560px); max-width: 100%; max-height: 88vh; overflow-y: auto;
  padding: var(--sp-28);
}
:root[data-mode="web-mobile"] .nr-modal { padding: var(--sp-12); align-items: flex-end; }
:root[data-mode="web-mobile"] .nr-modal-card { width: 100%; max-height: 92vh; }
:root[data-mode="native-app"] .nr-modal { padding: 0; align-items: flex-end; }
:root[data-mode="native-app"] .nr-modal-card {
  width: 100%; max-height: 92%; border-radius: var(--r-26) var(--r-26) 0 0;
  padding: var(--sp-10) var(--sp-20) var(--sp-32);
}
.nr-sheet-grabber {
  display: none; width: 38px; height: 4px; border-radius: var(--r-pill);
  background: var(--rule); margin: var(--sp-4) auto var(--sp-12);
}
:root[data-mode="native-app"] .nr-sheet-grabber { display: block; }
/* inside the device frame the sheet is bounded by the canvas, not the viewport */
.demo-canvas .nr-modal { position: absolute; }

/* ========================================================================== */
/* Misc                                                                       */
/* ========================================================================== */

/* Deep ink cards invert the muted end of the scale: #5F6265 would be unreadable
 * on #10303C. One class re-points the tokens for everything inside. */
.nr-on-ink { --text-muted: #B9BBBE; --positive: #7BD3A0; --negative: #F2A0A5; --ink-text: #fff; }
:root[data-theme="dark"] .nr-on-ink { --text-muted: #9DAEB8; --positive: #4FBE8A; --negative: #F0616B; --ink-text: #fff; }
.nr-topbar { --text-muted: #B9BBBE; }
:root[data-theme="dark"] .nr-topbar { --text-muted: #9DAEB8; --text-faint: #B9C6CE; }

/* Touch targets: at least 44x44 in both narrow versions. The desktop layout keeps
 * the prototype's denser metrics, which is correct for pointer input. */
:root[data-mode="web-mobile"] .nr-press,
:root[data-mode="native-app"] .nr-press { min-height: 44px; min-width: 44px; }
:root[data-mode="web-mobile"] .nr-week7,
:root[data-mode="native-app"] .nr-week7 { --gap: var(--sp-4); }
/* controls whose visual box must not grow get an invisible 44x44 hit area instead */
.nr-tap-pad { position: relative; }
:root[data-mode="web-mobile"] .nr-tap-pad,
:root[data-mode="native-app"] .nr-tap-pad { min-height: 0; }
:root[data-mode="web-mobile"] .nr-tap-pad::after,
:root[data-mode="native-app"] .nr-tap-pad::after {
  content: ""; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: max(100%, 44px); height: max(100%, 44px);
}
.demo-short { display: none; }
/* The shell gained a scenario console; at 1280 the bar has to shed the brand
 * descriptor and two long labels to stay on one row. */
@media (max-width: 1440px) {
  .demo-brand > div > div:nth-child(2) { display: none; }
  [data-act="about"] .demo-long, [data-act="reset"] .demo-long { display: none; }
  [data-act="about"] .demo-short, [data-act="reset"] .demo-short { display: inline; }
  .demo-bar { gap: var(--sp-8); }
}
@media (max-width: 720px) {
  .demo-btn, .demo-seg { min-height: 44px; }
  /* the shell must not eat the screen before the product appears */
  .demo-long { display: none; }
  .demo-short { display: inline; }
  .demo-bar { gap: var(--sp-6); padding: var(--sp-6) var(--sp-10); }
  .demo-brand > div > div:nth-child(2) { display: none; }
  .demo-chip { font-size: var(--fs-10); padding: var(--sp-5) var(--sp-8); }
  .demo-bar-spacer { flex-basis: 100%; }
  .demo-btn, .demo-seg { padding: var(--sp-6) var(--sp-10); font-size: var(--fs-11); }
}

/* opt-in entrance animations — added only when an element is new (js/anim.js) */
.nr-rise { animation: nrRise 0.18s ease-out; }
.nr-rise-slow { animation: nrRise var(--d-base) var(--ease); }
.nr-slide { animation: nrSlideIn var(--d-slow) var(--ease); }
:root[data-mode="native-app"] .nr-modal-card.nr-rise { animation: nrSheetUp var(--d-slow) var(--ease); }

.nr-skel { background: var(--surface-muted); animation: nrPulse 1.2s ease-in-out infinite; border-radius: var(--r-pill); }
.nr-spin {
  width: 14px; height: 14px; border-radius: var(--r-pill); display: inline-block;
  border: 2px solid var(--spinner-track); border-top-color: var(--on-accent);
  animation: nrSpin 0.7s linear infinite;
}
.nr-bar-anim { animation: nrBar var(--d-slow) var(--ease) both; }
.nr-stamp { animation: nrStamp var(--d-slow) var(--ease) both; }
.nr-count { font-variant-numeric: tabular-nums; }

/* skip link — CSS only, so no inline event handler is needed */
.nr-skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--surface); color: var(--text-strong);
  font: 600 var(--fs-13) var(--font-sans); padding: var(--sp-10) var(--sp-14);
  border-radius: 0 0 var(--r-10) 0; box-shadow: var(--shadow-2);
}
.nr-skip:focus { left: var(--sp-8); top: var(--sp-8); border-radius: var(--r-10); }
@media (max-width: 374px) { .nr-main { padding-left: var(--sp-12); padding-right: var(--sp-12); } }

/* Forcing web-desktop onto a narrow window is allowed (the selector works in any
 * direction), so the multi-column grids collapse when there is genuinely no room
 * rather than squeezing. Density, sidebar and table form still follow the mode. */
@media (max-width: 900px) {
  .nr-grid { grid-template-columns: minmax(0, 1fr); }
  .nr-kpis { flex-wrap: wrap; gap: var(--sp-16) var(--sp-20); }
  .nr-main { padding-left: var(--sp-20); padding-right: var(--sp-20); }
  .nr-cards { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
}
