/* =====================================================================
   Alpine — design tokens

   DIRECTION: instrument, not document.

   The previous palette took its cues from the payslip itself — off-white
   paper ruled in hairlines, monospace as the primary face. It read as a
   scanned form, and it was one hairline away from the house style every
   generated admin panel arrives in.

   This one takes its cues from what the tool *is* rather than what it
   reads. An assessor operates it all day to decide whether a soldier
   gets a house. So: instrument modules floating on a tinted deck,
   separated by air and shadow rather than ruled lines, with one gauge
   as the centrepiece.

   Alpine's navy and gold are the client's own, and gold on navy is
   Malaysian Army rank insignia — the connection is real, so gold is
   promoted here from decoration to a job: it marks where you are and
   what rank someone holds. It still never carries meaning alone, because
   it sits near 2:1 on white; every semantic colour stays separate.
   ===================================================================== */

:root {
  /* --- the deck: cool, tinted, so a white module genuinely lifts ---- */
  --deck:       #e7ecf1;
  --deck-deep:  #dbe3ea;
  --surface:    #ffffff;
  --raised:     #f2f5f8;
  --sunken:     #e9eef3;

  /* Rules survive only where a table genuinely needs a row boundary.
     Everywhere else, separation is done with space and shadow. */
  --rule:       #e3e9ef;
  --rule-firm:  #c6d1dc;

  /* --- ink --- */
  --ink:        #101c27;
  --ink-2:      #47576a;
  --ink-3:      #7d8b9b;

  /* --- buttons: a primary that stays visible on either deck --- */
  --btn-bg:     #17273a;
  --btn-bg-h:   #22374f;
  --btn-ink:    #ffffff;

  /* --- Alpine, from the logo --- */
  --navy:       #111d29;
  --navy-2:     #1e3247;
  --navy-lift:  #2c4a66;
  --gold:       #c8963f;
  --gold-lift:  #e0b066;
  --gold-wash:  #fbf3e4;

  /* --- meaning. deliberately not the brand accent --- */
  --balanced:      #0d6a4a;
  --balanced-bg:   #e4f2eb;
  --hold:          #8a5a00;
  --hold-bg:       #fdf1dc;
  --broken:        #b3261e;
  --broken-bg:     #fbe9e7;
  --settled:       #1b6ba8;
  --settled-bg:    #e7f1f9;

  /* --- type ---------------------------------------------------------
     Archivo carries a width axis. Section labels are set expanded and
     tracked out, which is how instrument plates are engraved — it gives
     the chrome a voice without adding a third family.

     IBM Plex Mono sets every figure. Numbers are the content in this
     tool, so they get the face that was drawn for them; the difference
     from the body text should be obvious at arm's length. */
  --sans: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --t-micro: 10.5px;
  --t-small: 12.5px;
  --t-body:  14.5px;
  --t-lead:  16px;
  --t-fig:   18.5px;
  --t-sum:   25px;
  --t-head:  33px;

  /* --- geometry --- */
  --r-sm: 6px;
  --r:    10px;
  --r-lg: 14px;
  --r-xl: 20px;

  --gap-1: 4px;
  --gap-2: 8px;
  --gap-3: 12px;
  --gap-4: 18px;
  --gap-5: 26px;
  --gap-6: 40px;

  --rail: 228px;
  --panel: 330px;

  /* --- depth: modules on a deck ------------------------------------
     Shadows are tinted navy rather than neutral black, and every module
     carries a hairline inner top-light so it reads as a physical plate
     rather than a floating rectangle. */
  --lift-1: 0 1px 2px rgba(16, 28, 39, .05);
  --lift-2: 0 1px 2px rgba(16, 28, 39, .05), 0 6px 16px -8px rgba(30, 50, 71, .22);
  --lift-3: 0 2px 5px rgba(16, 28, 39, .07), 0 18px 40px -14px rgba(30, 50, 71, .32);
  --lift-4: 0 4px 10px rgba(16, 28, 39, .09), 0 32px 64px -20px rgba(30, 50, 71, .40);
  --edge:   inset 0 1px 0 rgba(255, 255, 255, .9);

  /* --- motion -------------------------------------------------------
     One easing for movement, one for things that grow. Durations are
     short: this is a tool someone drives hundreds of times a day, and
     anything longer than a fifth of a second stops feeling like
     response and starts feeling like waiting. */
  --ease:      cubic-bezier(.2, .7, .3, 1);
  --ease-out:  cubic-bezier(.16, 1, .3, 1);
  --ease-in:   cubic-bezier(.5, 0, .75, 0);

  --t-fast:  120ms;
  --t-mid:   200ms;
  --t-slow:  320ms;

  color-scheme: light;
}

/* =====================================================================
   Dark — the same instrument at night.

   The deck goes to a deep navy-black so a raised module still genuinely
   lifts; ink inverts to a cool near-white; gold brightens a step because
   it now carries the accent against dark rather than sitting on white.
   Every colour token is redefined so nothing hard-codes a light value.

   Three states: an explicit choice stamps data-theme; the unset default
   follows the system; the manual toggle wins in both directions.
   ===================================================================== */
/* The dark palette itself, applied by an explicit dark choice OR by a
   system that prefers dark when no explicit light choice is set. */
:root[data-theme="dark"] { color-scheme: dark; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --deck:       #0b0d10;
    --deck-deep:  #060708;
    --surface:    #16181d;
    --raised:     #1e2229;
    --sunken:     #0e1013;

    --rule:       #262a31;
    --rule-firm:  #3a414b;

    --ink:        #ecf0f4;
    --ink-2:      #a7b0bb;
    --ink-3:      #6f7884;

    --navy:       #0a0c0f;
    --navy-2:     #242832;
    --navy-lift:  #343b47;
    --gold:       #d7a74d;
    --gold-lift:  #e8bd6f;
    --gold-wash:  #241d0f;
    --btn-bg: #2c333f; --btn-bg-h: #3a4250; --btn-ink: #fff;

    --balanced:      #40cb98;  --balanced-bg:   #10231b;
    --hold:          #e1a93b;  --hold-bg:       #29200f;
    --broken:        #f2685f;  --broken-bg:     #291411;
    --settled:       #57a9e2;  --settled-bg:    #10202c;

    --lift-1: 0 1px 2px rgba(0,0,0,.45);
    --lift-2: 0 1px 2px rgba(0,0,0,.45), 0 6px 16px -8px rgba(0,0,0,.60);
    --lift-3: 0 2px 6px rgba(0,0,0,.55), 0 18px 40px -14px rgba(0,0,0,.66);
    --lift-4: 0 4px 12px rgba(0,0,0,.60), 0 32px 64px -20px rgba(0,0,0,.76);
    --edge:   inset 0 1px 0 rgba(255,255,255,.05);

    --glass-bg:  rgba(22,24,29,.74);
    --glass-brd: rgba(255,255,255,.08);
  }
}
/* The same dark values under the explicit toggle, so choosing dark works
   even when the system is light. Kept in sync with the block above. */
:root[data-theme="dark"] {
  --deck:#0b0d10; --deck-deep:#060708; --surface:#16181d; --raised:#1e2229; --sunken:#0e1013;
  --rule:#262a31; --rule-firm:#3a414b;
  --ink:#ecf0f4; --ink-2:#a7b0bb; --ink-3:#6f7884;
  --navy:#0a0c0f; --navy-2:#242832; --navy-lift:#343b47;
  --gold:#d7a74d; --gold-lift:#e8bd6f; --gold-wash:#241d0f; --btn-bg:#2c333f; --btn-bg-h:#3a4250; --btn-ink:#fff;
  --balanced:#40cb98; --balanced-bg:#10231b;
  --hold:#e1a93b; --hold-bg:#29200f;
  --broken:#f2685f; --broken-bg:#291411;
  --settled:#57a9e2; --settled-bg:#10202c;
  --lift-1:0 1px 2px rgba(0,0,0,.45);
  --lift-2:0 1px 2px rgba(0,0,0,.45), 0 6px 16px -8px rgba(0,0,0,.60);
  --lift-3:0 2px 6px rgba(0,0,0,.55), 0 18px 40px -14px rgba(0,0,0,.66);
  --lift-4:0 4px 12px rgba(0,0,0,.60), 0 32px 64px -20px rgba(0,0,0,.76);
  --edge:inset 0 1px 0 rgba(255,255,255,.05);
  --glass-bg:rgba(22,24,29,.74); --glass-brd:rgba(255,255,255,.08);
}

/* Safe-area insets, so the mobile shell clears notches and home bars. */
:root {
  /* Frosted-glass surfaces (mobile nav, sheets). Light defaults; dark overrides above. */
  --glass-bg:   rgba(255,255,255,.72);
  --glass-brd:  rgba(16,28,39,.10);
  --glass-blur: 18px;

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
}

/* Motion is a preference, not a default. Everything below honours it —
   transitions collapse to near-zero rather than being removed, so state
   changes still land instantly instead of appearing not to happen. */
@media (prefers-reduced-motion: reduce) {
  :root { --t-fast: 1ms; --t-mid: 1ms; --t-slow: 1ms; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

/* =====================================================================
   Alpine — base

   Modules on a deck. Separation is done with space and shadow; a ruled
   line appears only where a table genuinely needs a row boundary.
   ===================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* Only the ROOT clips sideways overflow. Putting overflow-x:hidden on body
   as well turned body into a second scroll container (with nothing of its
   own to scroll), and with overscroll-behavior set on it a real wheel event
   was consumed there and never reached the page scroller — the page would
   not scroll from the mouse at all, while window.scrollTo still worked.
   overscroll-behavior lives here, on the element that actually scrolls. */
html { overflow-x: hidden; overscroll-behavior-y: none; }
/* The hidden attribute must win over any display-setting class (.grid, .row). */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--deck);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  font-variation-settings: "wdth" 100;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  touch-action: manipulation;   /* no double-tap zoom */
}

h1, h2, h3, h4 { margin: 0; font-weight: 650; letter-spacing: -.018em; text-wrap: balance; }
h1 { font-size: var(--t-head); letter-spacing: -.028em; }
h2 { font-size: var(--t-lead); }
h3 { font-size: var(--t-body); font-weight: 640; }
p  { margin: 0; }

button, input, select, textarea { font: inherit; color: inherit; }

a { color: var(--navy-lift); text-decoration-thickness: 1px; text-underline-offset: 2px; }

/* Keyboard focus must be obvious. This tool is operated fast. */
:focus-visible {
  outline: 2px solid var(--navy-lift);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* --- figures ------------------------------------------------------
   Numbers are the content, so they get the face drawn for them. Always
   tabular: a column of ringgit that does not line up is a column you
   cannot scan. */
.fig, .mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}
.fig { font-size: var(--t-fig); font-weight: 500; }
.fig-sum { font-family: var(--mono); font-variant-numeric: tabular-nums;
           font-size: var(--t-sum); font-weight: 600; letter-spacing: -.03em; }

/* --- the engraved label -------------------------------------------
   The signature typographic move. Archivo's width axis is pushed out and
   the tracking opened up, so a section label reads like the etched
   lettering on an instrument plate rather than a small-caps caption.
   Used for every field name and every panel heading eyebrow. */
.field {
  font-family: var(--sans);
  font-variation-settings: "wdth" 118;
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: block;
}

.muted   { color: var(--ink-2); }
.quiet   { color: var(--ink-3); }
.small   { font-size: var(--t-small); }
.right   { text-align: right; }
.grow    { flex: 1; min-width: 0; }
.row     { display: flex; align-items: center; gap: var(--gap-3); }
.stack   { display: flex; flex-direction: column; }
.hidden  { display: none !important; }

/* --- app frame ---------------------------------------------------- */

.app {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  min-height: 100vh;
}

.main {
  min-width: 0;
  padding: var(--gap-5) var(--gap-5) var(--gap-6);
}

.view { max-width: 1180px; }

.view-head {
  display: flex;
  align-items: flex-end;
  gap: var(--gap-3);
  margin-bottom: var(--gap-5);
}
.view-head p { color: var(--ink-2); margin-top: 5px; font-size: var(--t-body); }

.grid { display: grid; gap: var(--gap-3); }
.g-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* --- responsive ---------------------------------------------------- */

@media (max-width: 1080px) {
  .g-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid[style*="var(--panel)"] { grid-template-columns: minmax(0, 1fr) !important; }
  .grid[style*="1.25fr"] { grid-template-columns: minmax(0, 1fr) !important; }
}

/* =====================================================================
   Mobile shell — a floating glass bottom bar instead of the side rail.

   The rail is a desktop instrument panel; on a phone the same sections
   live in a frosted, floating tab bar within thumb reach, and the less-
   used controls (Rules, theme, sign out) move into an account sheet.
   ===================================================================== */
.tabbar, .sheet, .sheet-backdrop { display: none; }

@media (max-width: 820px) {
  .app { grid-template-columns: 1fr; }
  .app > .rail { display: none; }
  .app > .main {
    padding: calc(var(--safe-t) + var(--gap-3)) calc(var(--safe-r) + var(--gap-3))
             calc(74px + var(--safe-b) + var(--gap-4)) calc(var(--safe-l) + var(--gap-3));
  }
  .view-head { margin-bottom: var(--gap-4); }
  .g-2 { grid-template-columns: minmax(0, 1fr); }
  .g-4 { grid-template-columns: 1fr 1fr; }
  .grid.dl-grid { grid-template-columns: 1fr 1fr; gap: var(--gap-4) var(--gap-4); }
  .grid.dl-grid .field { letter-spacing: .06em; }
  h1 { font-size: 27px; }

  /* Detail tabs: tighter so the four fit, and scroll if they still don't. */
  .tabs { gap: 0; margin-bottom: var(--gap-3);
    -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs .tab { padding: 9px 13px 11px; font-size: var(--t-small); }

  /* The head on a phone: title on its own line, then search + action share
     a row so the action is reachable without eating a whole button of height. */
  .view-head { flex-direction: row; flex-wrap: wrap; align-items: center;
    gap: var(--gap-2) var(--gap-3); margin-bottom: var(--gap-4); }
  .view-head .grow { flex-basis: 100%; }
  .view-head p { font-size: var(--t-body); }
  .view-head .inp { flex: 1 1 100%; min-width: 0; max-width: none !important; }
  .view-head .btn { flex: 1; }
  .view-head .btn.quiet { flex: none; }
  .view { max-width: 100%; }

  /* A data table is a desktop shape. On a phone each row becomes a card:
     name on top, the two chips beneath, the timestamp muted below. */
  .people-list .tw { overflow-x: visible; }
  .people-list table, .people-list thead, .people-list tbody,
  .people-list tr, .people-list td { display: block; }
  .people-list thead { display: none; }
  .people-list tbody tr.click {
    padding: 15px var(--gap-4);
    border-bottom: 1px solid var(--rule);
    display: grid; grid-template-columns: 1fr auto; gap: 10px 12px; align-items: center;
  }
  .people-list tbody tr.click td { padding: 0; border: 0; }
  .people-list tbody tr.click td:nth-child(1) { grid-column: 1 / -1; }
  .people-list tbody tr.click td:nth-child(1) > div:first-child { font-size: var(--t-lead); }
  .people-list tbody tr.click td:nth-child(2) { grid-column: 1; grid-row: 2; }
  .people-list tbody tr.click td:nth-child(3) { grid-column: 2; grid-row: 2; justify-self: end; }
  .people-list tbody tr.click td:nth-child(4),
  .people-list tbody tr.click td:nth-child(5) { display: none; }
  .people-list tbody tr.click td:nth-child(6) {
    grid-column: 1 / -1; grid-row: 3; text-align: left; }
  .people-list tr.click td:first-child::before { display: none; }
  .people-list tbody tr.click:active { background: var(--sunken); }

  /* A data table (Projects): name on top, then labelled figures. */
  .data-list .tw { overflow-x: visible; }
  .data-list table, .data-list thead, .data-list tbody,
  .data-list tr, .data-list td { display: block; }
  .data-list thead { display: none; }
  .data-list tbody tr { padding: 15px var(--gap-4); border-bottom: 1px solid var(--rule); }
  .data-list tbody tr:last-child { border-bottom: 0; }
  .data-list tbody td { padding: 0; border: 0; text-align: left !important; }
  .data-list tbody td:nth-child(1) { margin-bottom: 8px; }
  .data-list tbody td:nth-child(1) > div:first-child { font-size: var(--t-lead); }
  .data-list td[data-label] {
    display: flex; justify-content: space-between; align-items: baseline;
    padding: 5px 0;
  }
  .data-list td[data-label]::before {
    content: attr(data-label); color: var(--ink-3);
    font-size: var(--t-small); font-weight: 600; letter-spacing: .02em;
  }
  .data-list td[data-label="Loan"] { font-weight: 600; }
  .data-list td[data-label="Notes"] { display: none; }

  /* Eligible-projects table: name on its own line, then Loan / Instalment /
     Headroom as labelled figures beneath. No sideways scroll. */
  .proj-table .tw, .card-body.flush .tw { overflow-x: visible; }
  .proj-table, .proj-table thead, .proj-table tbody,
  .proj-table tr, .proj-table td { display: block; }
  .proj-table thead { display: none; }
  .proj-table tbody tr { padding: 13px var(--gap-4); border-bottom: 1px solid var(--rule); }
  .proj-table tbody tr:last-child { border-bottom: 0; }
  .proj-table tbody td { padding: 0; border: 0; text-align: left !important; }
  .proj-table tbody td:nth-child(1) { margin-bottom: 9px; }
  .proj-table tbody td:nth-child(2),
  .proj-table tbody td:nth-child(3) {
    display: inline-flex; align-items: baseline; gap: 6px; margin-right: 18px; font-size: var(--t-small);
  }
  .proj-table tbody td:nth-child(2)::before { content: 'Loan'; }
  .proj-table tbody td:nth-child(3)::before { content: 'Instalment'; }
  .proj-table tbody td:nth-child(2)::before,
  .proj-table tbody td:nth-child(3)::before {
    color: var(--ink-3); font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em;
  }
  .proj-table tbody td:nth-child(4) { margin-top: 10px; }

  /* Reading tables (income / deductions): fixed layout so the figure column
     never gets pushed off-screen; the source quote truncates to fit. */
  .reading-group .tw { overflow-x: visible; }
  .reading-table { table-layout: fixed; width: 100%; }
  .reading-table td { padding-left: var(--gap-3); padding-right: var(--gap-3); }
  .reading-table td:nth-child(1) { width: auto; }
  .reading-table td:nth-child(2) { width: 88px; }
  .reading-table td:nth-child(3) { display: none; }   /* the reconciliation row's tint carries agree/off */
  .reading-table .quote { max-width: 100%; }
  .reading-facts { grid-template-columns: 1fr 1fr; }

  /* Approval cards: info over a full-width action row on a phone. */
  .approval-row { flex-direction: column; align-items: stretch; gap: var(--gap-3); }
  .approval-acts { width: 100%; }
  .approval-acts .btn { flex: 1; }

  /* Press feedback — answers the tap, nothing gratuitous. */
  .people-list tbody tr.click:active,
  .data-list tbody tr:active { transform: scale(.992); transition: transform var(--t-fast) var(--ease); }
  .card { transition: transform var(--t-fast) var(--ease); }

  .tabbar {
    display: flex;
    position: fixed; left: 50%; transform: translateX(-50%);
    bottom: calc(var(--safe-b) + 10px);
    width: min(460px, calc(100% - 20px));
    gap: 2px; padding: 6px;
    background: var(--glass-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.7);
    backdrop-filter: blur(var(--glass-blur)) saturate(1.7);
    border: 1px solid var(--glass-brd);
    border-radius: 22px;
    box-shadow: var(--lift-3);
    z-index: 50;
  }
  .tabbar .tab {
    flex: 1; position: relative;
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    padding: 8px 2px; min-height: 48px;
    border: 0; background: transparent; cursor: pointer;
    color: var(--ink-3); border-radius: 15px;
    transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
                transform var(--t-fast) var(--ease);
    -webkit-tap-highlight-color: transparent;
  }
  .tabbar .tab svg { width: 21px; height: 21px; stroke: currentColor; fill: none; }
  .tabbar .tab span { font-size: 10px; font-weight: 650; letter-spacing: .01em; }
  .tabbar .tab.on { color: var(--gold-lift); background: var(--gold-wash); }
  .tabbar .tab:active { transform: scale(.92); }
  .tabbar .tab .tab-badge {
    position: absolute; top: 4px; right: calc(50% - 20px);
    min-width: 16px; height: 16px; padding: 0 4px;
    display: grid; place-items: center;
    font: 700 10px/1 var(--mono); color: #fff;
    background: var(--broken); border-radius: 8px;
  }

  /* account sheet */
  .sheet-backdrop {
    display: block; position: fixed; inset: 0; z-index: 60;
    background: rgba(0,0,0,.42);
    opacity: 0; pointer-events: none;
    transition: opacity var(--t-mid) var(--ease);
  }
  .sheet-backdrop.open { opacity: 1; pointer-events: auto; }
  .sheet {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: 61;
    background: var(--surface); color: var(--ink);
    border-top: 1px solid var(--rule);
    border-radius: 22px 22px 0 0;
    padding: var(--gap-3) var(--gap-4) calc(var(--safe-b) + var(--gap-4));
    box-shadow: var(--lift-4);
    transform: translateY(101%);
    transition: transform var(--t-slow) var(--ease-out);
  }
  .sheet.open { transform: translateY(0); }
  .sheet .grip { width: 40px; height: 4px; border-radius: 2px;
    background: var(--rule-firm); margin: 4px auto var(--gap-3); }
  .sheet-who { display: flex; align-items: center; gap: 12px; margin-bottom: var(--gap-3);
    padding-bottom: var(--gap-3); border-bottom: 1px solid var(--rule); }
  .sheet-who .avatar { width: 42px; height: 42px; font-size: 16px; }
  .sheet-who .who-name { font-weight: 680; font-size: var(--t-lead); }
  .sheet-who .who-role { color: var(--ink-3); font-size: var(--t-small); }
  .sheet-row {
    display: flex; align-items: center; gap: 12px; width: 100%;
    padding: 13px 6px; border: 0; background: transparent; cursor: pointer;
    color: var(--ink); font: inherit; font-size: var(--t-lead); text-align: left;
    border-radius: 12px; -webkit-tap-highlight-color: transparent;
  }
  .sheet-row:active { background: var(--sunken); }
  .sheet-row svg { width: 20px; height: 20px; color: var(--ink-3); flex: none; }
  .sheet-row .grow { flex: 1; }
  .seg { display: inline-flex; gap: 2px; padding: 3px; background: var(--sunken);
    border-radius: 11px; }
  .seg button { border: 0; background: transparent; color: var(--ink-2);
    padding: 6px 12px; border-radius: 9px; font: 600 var(--t-small)/1 var(--sans); cursor: pointer; }
  .seg button.on { background: var(--surface); color: var(--ink); box-shadow: var(--lift-1); }

  .hswitch { width: 46px; height: 27px; border-radius: 14px; border: 0; flex: none;
    background: var(--rule-firm); position: relative; cursor: pointer;
    transition: background var(--t-fast) var(--ease); -webkit-tap-highlight-color: transparent; }
  .hswitch .knob { position: absolute; top: 3px; left: 3px; width: 21px; height: 21px;
    border-radius: 50%; background: #fff; box-shadow: var(--lift-1);
    transition: transform var(--t-fast) var(--ease); }
  .hswitch.on { background: var(--balanced); }
  .hswitch.on .knob { transform: translateX(19px); }
}

/* =====================================================================
   Motion
   ===================================================================== */

/* --- page transitions ---------------------------------------------
   The outgoing view leaves without moving; the incoming one rises a few
   pixels as it arrives. Asymmetric on purpose — matching the two makes
   a swap read as a crossfade of equals, where what we want is the sense
   that the new screen came forward. */
@keyframes view-in  { from { opacity: 0; } }
@keyframes view-out { to   { opacity: 0; } }

::view-transition-old(page) { animation: view-out 70ms linear both; }
::view-transition-new(page) { animation: view-in  110ms linear both; }

/* The rail must not fade with the page — it is the thing that stays put
   while everything else changes. */
::view-transition-group(rail),
::view-transition-group(marker) { animation-duration: 130ms; }

/* Fallback for browsers without the API: the same reveal, applied to the
   slot as it is committed. */
.view-slot { animation: view-in 110ms linear both; }

/* --- skeletons ------------------------------------------------------
   A skeleton is a promise about layout, so it must be quiet enough not
   to be mistaken for content. The sweep is slow and low-contrast. */
.sk {
  display: block;
  border-radius: 5px;
  background:
    linear-gradient(90deg, transparent 20%, rgba(255,255,255,.65) 50%, transparent 80%),
    var(--sunken);
  background-size: 220% 100%, auto;
  animation: sk-sweep 1400ms linear infinite;
}
@keyframes sk-sweep { from { background-position: 120% 0, 0 0; } to { background-position: -120% 0, 0 0; } }

.sk-row td { padding: 13px var(--gap-4) !important; }
.sk-head { opacity: .85; }

.main.busy { cursor: progress; }

/* --- the reveal ----------------------------------------------------
   Rows start invisible so the stagger has something to reveal. If
   JavaScript never runs the animation, the rule below still shows them
   — an interface that stays blank because an animation failed is the
   worst possible trade. */
@media (prefers-reduced-motion: no-preference) {
  #rows tr, .stack > .card, .grid > .stat { opacity: 1; }
}

/* =====================================================================
   Alpine — components

   Everything is a module bolted to a deck: a white plate, a tight
   shadow, a hairline of top-light along its upper edge. That inner edge
   is what stops a card reading as a flat rectangle — it is the same
   trick a physical instrument panel uses, and it is why this does not
   need ruled lines to feel organised.
   ===================================================================== */

/* ------------------------------------------------------------------ */
/* The rail                                                            */
/* ------------------------------------------------------------------ */

.rail {
  position: sticky; top: 0;
  display: flex; flex-direction: column;
  height: 100vh;
  padding: var(--gap-4) var(--gap-3) var(--gap-3);
  background: var(--navy);
  color: #dfe7ee;
  view-transition-name: rail;
}

/* A soft gold bloom at the top of the rail. The only purely atmospheric
   thing in the interface, and it earns its place by making the panel
   read as lit rather than filled. */
.rail::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 240px;
  background: radial-gradient(120% 70% at 0% 0%, rgba(200,150,63,.16), transparent 70%);
  pointer-events: none;
}

.brand { display: flex; align-items: center; gap: 10px; padding: 0 8px var(--gap-4); position: relative; }
.brand img { width: 30px; height: 30px; border-radius: 7px; object-fit: cover; }
.brand-mark {
  width: 30px; height: 30px; border-radius: 7px; flex: none;
  background: linear-gradient(150deg, var(--gold-lift), var(--gold));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45);
}
.brand b {
  display: block; font-size: 14px; font-weight: 680; letter-spacing: -.015em;
  color: #fff; line-height: 1.2;
}
.brand span {
  display: block; font-size: 9.5px; font-weight: 600; letter-spacing: .18em;
  text-transform: uppercase; color: var(--gold-lift);
  font-variation-settings: "wdth" 118;
}

.nav-scroll { position: relative; flex: 1; display: flex; flex-direction: column; gap: 1px; }

.nav-group {
  font-size: 9.5px; font-weight: 650; letter-spacing: .16em; text-transform: uppercase;
  font-variation-settings: "wdth" 118;
  color: rgba(223,231,238,.42);
  padding: var(--gap-4) 10px 7px;
}
.nav-group:first-child { padding-top: 2px; }

/* The indicator: one element that slides between items. Not a border
   redrawn on whichever button is current — that version could not
   animate, because the element that should have moved was destroyed and
   rebuilt on every render. */
.nav-marker {
  position: absolute; left: 0; right: 0; top: 0;
  border-radius: 9px;
  background: rgba(255,255,255,.10);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10);
  opacity: 0;
  transition: transform var(--t-mid) var(--ease), height var(--t-mid) var(--ease), opacity var(--t-fast);
  pointer-events: none;
  view-transition-name: marker;
}
/* The gold tab that marks the current section. Gold has a job here. */
.nav-marker::before {
  content: ''; position: absolute; left: 0; top: 9px; bottom: 9px; width: 2.5px;
  border-radius: 0 3px 3px 0; background: var(--gold-lift);
}

.nav-item {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 9px 10px;
  border: 0; border-radius: 9px; background: none;
  color: rgba(223,231,238,.72);
  font-size: var(--t-body); font-weight: 500; text-align: left;
  cursor: pointer;
  transition: color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.nav-item svg { width: 16px; height: 16px; flex: none; opacity: .8; transition: opacity var(--t-fast); }
.nav-item span { flex: 1; }
.nav-item:hover { color: #fff; }
.nav-item:hover svg { opacity: 1; }
.nav-item:active { transform: translateX(1px); }
.nav-item.on { color: #fff; font-weight: 600; }
.nav-item.on svg { opacity: 1; color: var(--gold-lift); }

.nav-count {
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  padding: 2px 7px; border-radius: 20px;
  background: rgba(255,255,255,.12); color: #fff;
}
.nav-count.urgent { background: var(--gold); color: #2a1c04; }

.rail-foot { margin-top: auto; padding-top: var(--gap-3); border-top: 1px solid rgba(255,255,255,.09); }
.who { display: flex; align-items: center; gap: 9px; padding: 0 4px var(--gap-3); }
.avatar {
  width: 28px; height: 28px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255,255,255,.11); color: #fff;
  font-size: 12px; font-weight: 650; text-transform: uppercase;
}
.who-name { font-size: 12.5px; font-weight: 600; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.who-role { font-size: 11px; color: rgba(223,231,238,.5); }
.rail-foot .btn.quiet { background: rgba(255,255,255,.08); color: #dfe7ee; border-color: transparent; }
.rail-foot .btn.quiet:hover { background: rgba(255,255,255,.15); color: #fff; }

/* Appearance switch in the rail. The rail is dark in either theme, so this
   is styled on translucent white rather than the light/dark tokens. */
.rail-appearance { padding: 0 4px var(--gap-3); }
.rail-appearance-label {
  display: block; font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(223,231,238,.5); font-weight: 600; margin-bottom: 7px;
}
.rail .seg { display: flex; gap: 2px; padding: 3px; width: 100%;
  background: rgba(255,255,255,.06); border-radius: 10px; }
.rail .seg button {
  flex: 1; border: 0; background: transparent; color: #a7b5c3; cursor: pointer;
  padding: 6px 4px; border-radius: 7px; font: 600 12px/1 var(--sans);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.rail .seg button:hover { color: #e7edf3; }
.rail .seg button.on { background: rgba(255,255,255,.15); color: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.28); }

/* ------------------------------------------------------------------ */
/* Cards — the module                                                  */
/* ------------------------------------------------------------------ */

.card {
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--lift-2), var(--edge);
  overflow: hidden;
}
.card-head {
  display: flex; align-items: center; gap: var(--gap-2);
  padding: var(--gap-3) var(--gap-4);
  background: linear-gradient(var(--surface), var(--raised));
  border-bottom: 1px solid var(--rule);
}
.card-head h3 { font-size: var(--t-body); font-weight: 650; }
.card-body { padding: var(--gap-4); }
.card-body.flush { padding: 0; }

.stat {
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: var(--gap-4);
  box-shadow: var(--lift-2), var(--edge);
  position: relative; overflow: hidden;
  transition: transform var(--t-mid) var(--ease), box-shadow var(--t-mid) var(--ease);
}
.stat:hover { transform: translateY(-1px); box-shadow: var(--lift-3), var(--edge); }
.stat .v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 27px; font-weight: 600; letter-spacing: -.035em;
  margin-top: 7px; line-height: 1.1;
}
.stat .d { font-size: var(--t-small); color: var(--ink-3); margin-top: 4px; }

/* The lead statistic is the one someone looks at first, so it is the one
   that reads as lit rather than printed. */
.stat.lead { background: linear-gradient(160deg, var(--navy-2), var(--navy)); color: #fff; }
.stat.lead::after {
  content: ''; position: absolute; inset: auto -30% -60% auto; width: 200px; height: 200px;
  background: radial-gradient(circle, rgba(200,150,63,.22), transparent 65%);
}
.stat.lead .field, .stat.lead .d { color: rgba(255,255,255,.62); }

/* ------------------------------------------------------------------ */
/* Tables                                                              */
/* ------------------------------------------------------------------ */

.tw { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
thead th {
  font-family: var(--sans); font-variation-settings: "wdth" 118;
  font-size: var(--t-micro); font-weight: 650; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3); text-align: left;
  padding: 11px var(--gap-4); background: var(--raised);
  border-bottom: 1px solid var(--rule);
  position: sticky; top: 0; z-index: 2;
}
thead th.right { text-align: right; }
tbody td { padding: 11px var(--gap-4); border-bottom: 1px solid var(--rule); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }

/* A row that can be opened says so by lifting a gold edge on hover,
   rather than by changing colour — colour is spent on meaning here. */
tr.click { cursor: pointer; transition: background var(--t-fast) var(--ease); }
tr.click td:first-child { position: relative; }
tr.click td:first-child::before {
  content: ''; position: absolute; left: 0; top: 4px; bottom: 4px; width: 2.5px;
  border-radius: 0 3px 3px 0; background: var(--gold);
  transform: scaleY(0); transform-origin: center;
  transition: transform var(--t-mid) var(--ease-out);
}
/* Hover only where there is a real pointer — on touch it sticks after a
   tap and leaves a phantom-highlighted row. */
@media (hover: hover) {
  tr.click:hover { background: var(--raised); }
  tr.click:hover td:first-child::before { transform: scaleY(1); }
}
tr.click:focus-visible td:first-child::before { transform: scaleY(1); }
tr.click[aria-selected="true"] { background: var(--gold-wash); }
tr.click.unfit { opacity: .58; }

/* ------------------------------------------------------------------ */
/* Controls                                                            */
/* ------------------------------------------------------------------ */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 8px 15px; border-radius: 9px;
  border: 1px solid transparent;
  background: var(--btn-bg); color: var(--btn-ink);
  font-size: var(--t-body); font-weight: 580; letter-spacing: -.005em;
  cursor: pointer; white-space: nowrap;
  box-shadow: var(--lift-1), inset 0 1px 0 rgba(255,255,255,.13);
  transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease), opacity var(--t-fast);
}
.btn:hover { background: var(--btn-bg-h); box-shadow: var(--lift-2), inset 0 1px 0 rgba(255,255,255,.13); }
.btn:active { transform: translateY(1px); box-shadow: var(--lift-1); }
.btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }
.btn.lg { padding: 11px 18px; font-size: var(--t-lead); border-radius: 10px; }
.btn.sm { padding: 6px 11px; font-size: var(--t-small); border-radius: 7px; }
.btn.ghost { background: var(--surface); color: var(--ink); border-color: var(--rule-firm); box-shadow: var(--lift-1); }
.btn.ghost:hover { background: var(--raised); border-color: var(--ink-3); }
.btn.quiet { background: transparent; color: var(--ink-2); box-shadow: none; }
.btn.quiet:hover { background: var(--sunken); color: var(--ink); }
.btn.danger { background: var(--broken); }
.btn.danger:hover { background: #8f1e17; }

/* A button that is working says so in place, rather than by swapping to
   a word and hoping the person notices. */
.btn.busy { position: relative; color: transparent; pointer-events: none; }
.btn.busy::after {
  content: ''; position: absolute; inset: 0; margin: auto;
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid rgba(255,255,255,.3); border-top-color: #fff;
  animation: spin 620ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.lbl { display: block; margin-bottom: var(--gap-3); }
.lbl > .field { margin-bottom: 5px; }

.inp {
  width: 100%; padding: 9px 12px;
  border: 1px solid var(--rule-firm); border-radius: 9px;
  background: var(--surface); color: var(--ink);
  font-family: var(--mono); font-size: var(--t-body); text-align: right;
  box-shadow: inset 0 1px 2px rgba(16,28,39,.04);
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.inp:hover { border-color: var(--ink-3); }
.inp:focus {
  outline: none; border-color: var(--navy-lift);
  box-shadow: 0 0 0 3px rgba(44,74,102,.14), inset 0 1px 2px rgba(16,28,39,.04);
}
.inp.num { text-align: right; }
select.inp { appearance: none; background-image:
  linear-gradient(45deg, transparent 50%, var(--ink-3) 50%),
  linear-gradient(135deg, var(--ink-3) 50%, transparent 50%);
  background-position: calc(100% - 16px) 52%, calc(100% - 11px) 52%;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
  padding-right: 30px; cursor: pointer; }

/* ------------------------------------------------------------------ */
/* Chips, flags, ticks                                                 */
/* ------------------------------------------------------------------ */

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 20px;
  font-size: 11.5px; font-weight: 570; white-space: nowrap;
  background: var(--sunken); color: var(--ink-2);
}
.chip::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .75; }
.chip.plain::before { display: none; }
.chip.ok   { background: var(--balanced-bg); color: var(--balanced); }
.chip.bad  { background: var(--broken-bg);   color: var(--broken); }
.chip.hold { background: var(--hold-bg);     color: var(--hold); }
.chip.info { background: var(--settled-bg);  color: var(--settled); }

.flag {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 11px 13px; border-radius: var(--r);
  font-size: var(--t-small); line-height: 1.5;
}
.flag i { font-style: normal; font-size: 11px; line-height: 1.4; flex: none; }
.flag b { display: block; font-size: var(--t-body); font-weight: 620; margin-bottom: 2px; }
.flag.critical { background: var(--broken-bg);   color: #7a1a14; }
.flag.review   { background: var(--hold-bg);     color: #6b4600; }
.flag.info     { background: var(--settled-bg);  color: #114f7d; }

.tick { width: 16px; height: 16px; border-radius: 50%; display: grid; place-items: center;
        font-size: 9px; font-weight: 700; flex: none; }
.tick.ok   { background: var(--balanced-bg); color: var(--balanced); }
.tick.bad  { background: var(--broken-bg);   color: var(--broken); }
.tick.pend { background: var(--sunken);      color: var(--ink-3); }

/* ------------------------------------------------------------------ */
/* THE SIGNATURE — the reconciliation gauge                            */
/* ------------------------------------------------------------------ */
/* The product's whole promise in one instrument: four buckets that must
   add back to Jumlah Potongan exactly. Drawn as a machined gauge with a
   tick scale, because it is a measurement, not a chart. When the money
   does not reconcile a hatched void opens where the unaccounted amount
   is — hatched rather than coloured, because it is an absence and must
   not be mistaken for a fifth category. */

.recon {
  position: sticky; top: var(--gap-3); z-index: 20;
  background: linear-gradient(165deg, var(--navy-2), var(--navy));
  color: #fff;
  border-radius: var(--r-lg);
  padding: var(--gap-4);
  box-shadow: var(--lift-3), inset 0 1px 0 rgba(255,255,255,.09);
  overflow: hidden;
}
.recon::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 100%;
  background: radial-gradient(90% 60% at 100% 0%, rgba(200,150,63,.13), transparent 62%);
  pointer-events: none;
}
.recon.broken { box-shadow: var(--lift-3), inset 0 1px 0 rgba(255,255,255,.09), 0 0 0 1.5px var(--broken); }

.recon-top { display: flex; align-items: baseline; gap: var(--gap-3); margin-bottom: 11px; position: relative; }
.recon-top .field { color: rgba(255,255,255,.5); flex: 1; }
.recon-total {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: var(--t-sum); font-weight: 600; letter-spacing: -.03em;
}

/* The bar, with a tick scale beneath it — the detail that makes this an
   instrument rather than a progress bar. */
.recon-bar {
  display: flex; height: 34px; border-radius: 7px; overflow: hidden;
  background: rgba(0,0,0,.28);
  box-shadow: inset 0 2px 5px rgba(0,0,0,.35);
  position: relative;
}
.recon-bar::after {
  content: ''; position: absolute; inset: auto 0 0; height: 6px;
  background: repeating-linear-gradient(90deg,
    rgba(255,255,255,.22) 0 1px, transparent 1px 10%);
  pointer-events: none;
}

.recon-seg {
  display: grid; place-items: center;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 11.5px; font-weight: 600; color: #0f1a24;
  border-right: 1px solid rgba(0,0,0,.22);
  transition: flex-basis var(--t-slow) var(--ease-out);
  min-width: 0; overflow: hidden;
}
.recon-seg:last-child { border-right: 0; }
.seg-wajib  { background: linear-gradient(#dbe6f0, #c2d3e2); }
.seg-hutang { background: linear-gradient(#bcdcf3, #93c3e4); }
.seg-abai   { background: linear-gradient(#e6e9ec, #ccd3da); }
.seg-lain   { background: linear-gradient(#cfe6cd, #a9d0a6); }

/* The absence. */
.seg-gap {
  background:
    repeating-linear-gradient(45deg,
      rgba(255,120,110,.5) 0 5px, rgba(0,0,0,.18) 5px 10px);
  color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255,120,110,.65);
  animation: gap-pulse 2.2s var(--ease) infinite;
}
@keyframes gap-pulse { 50% { box-shadow: inset 0 0 0 1px rgba(255,120,110,1); } }

.recon-keys { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-3); margin-top: 11px; position: relative; }
.recon-key { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: rgba(255,255,255,.66); }
.recon-key i { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.recon-key .v { font-family: var(--mono); font-variant-numeric: tabular-nums; color: #fff; font-weight: 500; }

.recon-verdict { margin-left: auto; display: inline-flex; align-items: center; gap: 7px; font-size: var(--t-small); font-weight: 600; }
.recon-verdict.ok  { color: #7fe0b0; }
.recon-verdict.bad { color: #ff9d93; }
.recon-eq { font-family: var(--mono); font-size: 16px; font-weight: 600; }

/* ------------------------------------------------------------------ */
/* The verdict panel                                                   */
/* ------------------------------------------------------------------ */

.verdict { background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--lift-2), var(--edge); overflow: hidden; }
.verdict-head { padding: var(--gap-4); background: var(--raised); border-bottom: 1px solid var(--rule); }
.verdict-value { font-size: 25px; font-weight: 700; letter-spacing: -.03em; margin-top: 6px; line-height: 1.1; }
.verdict-sub { font-size: var(--t-small); color: var(--ink-3); margin-top: 3px; }
.verdict-head.ok  { background: linear-gradient(var(--balanced-bg), #d9ece2); }
.verdict-head.ok  .verdict-value { color: var(--balanced); }
.verdict-head.bad { background: linear-gradient(var(--broken-bg), #f7ddd9); }
.verdict-head.bad .verdict-value { color: var(--broken); }

/* A verdict carrying unresolved critical flags may not read as a green
   light — the next thing that happens is someone quoting a house on it.
   The engine's answer is unchanged; the confident fill is withdrawn. */
.verdict-head.held { background: repeating-linear-gradient(135deg, var(--hold-bg) 0 9px, #fbeacd 9px 18px); }
.verdict-head.held .verdict-value { color: var(--hold); }
.verdict-head.held .verdict-value::after { content: ' · not confirmed'; font-size: 12px; font-weight: 600; letter-spacing: 0; }

.hold-block { margin-top: var(--gap-3); padding-top: var(--gap-3); border-top: 1px solid rgba(138,90,0,.22); }
.hold-title { font-size: var(--t-small); font-weight: 650; color: #6b4600; margin-bottom: 5px; }
.hold-list { margin: 0; padding: 0; list-style: none; }
.hold-list li { font-size: var(--t-small); color: #6b4600; padding-left: 14px; position: relative; margin-top: 3px; }
.hold-list li::before { content: '▲'; position: absolute; left: 0; font-size: 8px; top: 4px; }

.test-row, .stat-row { display: flex; align-items: center; gap: 10px; padding: 9px var(--gap-4); border-bottom: 1px solid var(--rule); font-size: var(--t-small); }
.test-row span:nth-child(2) { flex: 1; }
.test-row .v, .stat-row .v { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink-2); }
.stat-row .field { flex: 1; }
.stat-row .v { font-size: var(--t-fig); font-weight: 600; color: var(--ink); letter-spacing: -.02em; }
.stat-row:last-child { border-bottom: 0; }

/* ------------------------------------------------------------------ */
/* The worksheet steps                                                 */
/* ------------------------------------------------------------------ */

.step { padding-top: var(--gap-4); margin-top: var(--gap-4); border-top: 1px solid var(--rule); }
.step:first-child { padding-top: 0; margin-top: 0; border-top: 0; }
.step-head { display: flex; align-items: center; gap: 10px; margin-bottom: 11px; }
.step-head h3 { flex: 1; font-size: var(--t-lead); }
.step-n {
  width: 22px; height: 22px; flex: none; border-radius: 7px;
  display: grid; place-items: center;
  background: var(--navy); color: var(--gold-lift);
  font-family: var(--mono); font-size: 11px; font-weight: 600;
}
.step-formula { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }

.led { border-radius: var(--r); overflow: hidden; background: var(--raised); }
.led-row { display: flex; align-items: center; gap: var(--gap-3); padding: 8px 13px; font-size: var(--t-small); }
.led-row:nth-child(odd) { background: rgba(255,255,255,.6); }
.led-row .v { margin-left: auto; font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: var(--t-body); }
.led-row.total { font-weight: 650; background: var(--surface); box-shadow: inset 0 1px 0 var(--rule-firm); }
.led-row.total .v { font-size: var(--t-fig); font-weight: 600; }
.led-row.note { color: var(--ink-3); }

/* ------------------------------------------------------------------ */
/* Message, upload, empty, modal, toast                                */
/* ------------------------------------------------------------------ */

.msg {
  margin: 0; padding: var(--gap-4);
  background: var(--navy); color: #e6edf3;
  border-radius: var(--r);
  font-family: var(--mono); font-size: var(--t-small); line-height: 1.75;
  white-space: pre-wrap; word-break: break-word;
  max-height: 460px; overflow: auto;
}

.drop {
  border: 1.5px dashed var(--rule-firm); border-radius: var(--r-lg);
  padding: var(--gap-5); text-align: center;
  background: var(--raised);
  transition: border-color var(--t-mid) var(--ease), background var(--t-mid) var(--ease), transform var(--t-mid) var(--ease);
}
.drop.over { border-color: var(--navy-lift); background: var(--settled-bg); transform: scale(1.006); }
.drop input[type=file] { display: none; }

.doc-busy { display: inline-flex; align-items: center; gap: 8px; font-size: var(--t-small); color: var(--ink-2); }
.spin { width: 13px; height: 13px; border-radius: 50%; border: 2px solid var(--rule-firm); border-top-color: var(--navy); animation: spin 620ms linear infinite; flex: none; }

.empty { padding: var(--gap-6) var(--gap-4); text-align: center; }
.empty h3 { font-size: var(--t-lead); margin-bottom: 5px; }
.empty p { font-size: var(--t-small); max-width: 46ch; margin: 0 auto; }

.modal-backdrop {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(16,28,39,.42);
  backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: var(--gap-4);
  animation: fade var(--t-mid) var(--ease-out) both;
}
@keyframes fade { from { opacity: 0; } }
.modal {
  width: min(460px, 100%);
  background: var(--surface); border-radius: var(--r-xl);
  box-shadow: var(--lift-4);
  max-height: 88vh; overflow: auto;
  animation: modal-in var(--t-slow) var(--ease-out) both;
}
@keyframes modal-in { from { opacity: 0; transform: translateY(14px) scale(.985); } }
.modal-head { display: flex; align-items: center; gap: var(--gap-3); padding: var(--gap-4) var(--gap-4) var(--gap-3); }
.modal-head h2 { flex: 1; font-size: var(--t-lead); }
.modal-body { padding: 0 var(--gap-4) var(--gap-4); }
.modal-body .lbl:last-of-type { margin-bottom: var(--gap-4); }

.toast-wrap { position: fixed; right: var(--gap-4); bottom: var(--gap-4); z-index: 200; display: flex; flex-direction: column; gap: var(--gap-2); }
.toast {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 15px; border-radius: var(--r);
  background: var(--navy); color: #fff;
  font-size: var(--t-small); box-shadow: var(--lift-3);
  max-width: 380px;
  animation: toast-in var(--t-slow) var(--ease-out) both;
}
@keyframes toast-in { from { opacity: 0; transform: translateY(10px) scale(.97); } }
.toast i { width: 6px; height: 6px; border-radius: 50%; background: var(--balanced); flex: none; }
.toast.bad { background: var(--broken); }
.toast.bad i { background: #fff; }

/* ------------------------------------------------------------------ */
/* Login                                                               */
/* ------------------------------------------------------------------ */

.login-page { min-height: 100vh; display: grid; place-items: center; padding: var(--gap-4); position: relative; overflow: hidden; background: var(--navy); }
.login-deck { position: absolute; inset: 0; background:
  radial-gradient(70% 55% at 22% 12%, rgba(200,150,63,.20), transparent 62%),
  radial-gradient(60% 50% at 82% 88%, rgba(44,74,102,.55), transparent 60%); }
.login-card {
  position: relative; width: min(400px, 100%);
  background: var(--surface); border-radius: var(--r-xl);
  padding: var(--gap-5); box-shadow: var(--lift-4);
  animation: modal-in 420ms var(--ease-out) both;
}
.login-card .brand { padding: 0 0 var(--gap-4); }
.login-card .brand b, .login-card .brand span { color: var(--ink); }
.login-card .brand span { color: var(--gold); }
.login-title { font-size: 21px; letter-spacing: -.025em; }
.login-sub { font-size: var(--t-small); color: var(--ink-3); margin: 4px 0 var(--gap-4); }

/* ------------------------------------------------------------------ */
/* Tabs                                                                */
/* ------------------------------------------------------------------ */

.tabs {
  position: relative;
  display: flex; gap: 2px;
  margin-bottom: var(--gap-4);
  border-bottom: 1px solid var(--rule);
  overflow-x: auto;
}
.tab {
  position: relative; z-index: 1;
  padding: 9px 14px 11px;
  border: 0; background: none; cursor: pointer;
  font-size: var(--t-body); font-weight: 520;
  color: var(--ink-3); white-space: nowrap;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.tab:hover { color: var(--ink); background: rgba(255,255,255,.55); }
.tab.on { color: var(--ink); font-weight: 640; }

.tab-marker {
  position: absolute; left: 0; bottom: -1px; height: 2px;
  background: var(--navy); border-radius: 2px 2px 0 0;
  opacity: 0;
  transition: transform var(--t-mid) var(--ease), width var(--t-mid) var(--ease), opacity var(--t-fast);
}
.tab-marker::after {
  content: ''; position: absolute; inset: -1px 0 auto; height: 2px;
  background: var(--gold); opacity: .55;
}

/* ------------------------------------------------------------------ */
/* Readings — what the model saw                                       */
/* ------------------------------------------------------------------ */

.reading-facts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--gap-3); padding: var(--gap-4);
  background: var(--raised); border-bottom: 1px solid var(--rule);
  font-size: var(--t-small);
}
.reading-group + .reading-group { border-top: 1px solid var(--rule); }
.reading-head { padding: var(--gap-3) var(--gap-4) 6px; }
.reading-table td { padding: 8px var(--gap-4); font-size: var(--t-small); border-bottom: 1px solid var(--rule); }

/* The words on the document the figure came from. Quiet, because it is
   evidence you consult rather than read — but present, because "where
   did 4,202.67 come from" is the question this panel exists to answer. */
.quote {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
  margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 46ch;
}

.reading-check td { background: var(--balanced-bg); border-bottom: 0; }
.reading-check.off td { background: var(--broken-bg); }

.reading-net {
  display: flex; align-items: center; justify-content: space-between; gap: var(--gap-3);
  padding: var(--gap-3) var(--gap-4); border-top: 1px solid var(--rule-firm); background: var(--surface);
}

.doc-head { cursor: pointer; user-select: none; }
.doc-head:hover { background: linear-gradient(var(--raised), var(--sunken)); }
.doc-caret { color: var(--ink-3); font-size: 11px; transition: transform var(--t-mid) var(--ease); }
.doc-head.open .doc-caret { transform: rotate(90deg); }
.doc-body[hidden] { display: none; }

/* Correcting a reading. The inputs sit where the figures were, so the
   column keeps its alignment and the eye does not have to re-find it. */
.amt-edit { max-width: 116px; padding: 4px 8px; font-size: var(--t-small); display: inline-block; }
.amt-edit[hidden], .amt-read[hidden] { display: none; }
.card.correcting { box-shadow: var(--lift-3), var(--edge), 0 0 0 1.5px var(--navy-lift); }
.card.correcting .card-head { background: linear-gradient(var(--settled-bg), #dceaf6); }

/* The pages a portal run walked through. A strip of steps above one
   large view — you are comparing pages, so the picture stays put and the
   selection moves. */
.shot-strip { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: var(--gap-3); }
.shot-tab {
  padding: 4px 9px; border: 1px solid var(--rule-firm); border-radius: 20px;
  background: var(--surface); color: var(--ink-2);
  font-size: 11px; cursor: pointer; white-space: nowrap;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.shot-tab:hover { background: var(--raised); color: var(--ink); }
.shot-tab.on { background: var(--navy); color: #fff; border-color: var(--navy); }
.shot-img { width: 100%; border-radius: var(--r); border: 1px solid var(--rule); display: block; }

/* ------------------------------------------------------------------ */
/* Payslip intake overlay                                              */
/* ------------------------------------------------------------------ */
.intake-overlay {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center; padding: var(--gap-4);
  background: rgba(0,0,0,.5);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  opacity: 0; transition: opacity var(--t-mid) var(--ease);
  pointer-events: none;   /* a fading or stray overlay must never eat a scroll */
}
.intake-overlay.open { opacity: 1; pointer-events: auto; }
.intake-card {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r-lg); box-shadow: var(--lift-4);
  padding: var(--gap-5) var(--gap-5) var(--gap-4);
  width: min(320px, 100%); text-align: center;
  transform: scale(.96); transition: transform var(--t-mid) var(--ease-out);
}
.intake-overlay.open .intake-card { transform: scale(1); }
.intake-spin {
  width: 34px; height: 34px; margin: 4px auto var(--gap-3);
  border: 3px solid var(--rule-firm); border-top-color: var(--gold);
  border-radius: 50%; animation: intake-spin .8s linear infinite;
}
@keyframes intake-spin { to { transform: rotate(360deg); } }
.intake-fail {
  width: 34px; height: 34px; margin: 4px auto var(--gap-3);
  display: grid; place-items: center; border-radius: 50%;
  background: var(--broken-bg); color: var(--broken); font-weight: 800; font-size: 18px;
}
.intake-title { font-size: var(--t-lead); font-weight: 660; }
.intake-file { color: var(--ink-2); font-size: var(--t-small); margin-top: 4px; word-break: break-word; }
.intake-hint { color: var(--ink-3); font-size: var(--t-small); margin-top: var(--gap-3); }
.intake-close { margin-top: var(--gap-3); }
@media (prefers-reduced-motion: reduce) { .intake-spin { animation-duration: 1.4s; } }
