/* ═══════════════════════════════════════════════════════════════════════
   Signal Design System 3.0 — foundation layer
   ═══════════════════════════════════════════════════════════════════════

   Washi paper, ink, stone, fog. The interface disappears; the information
   is the hero.

   HOW THIS FILE WORKS

   The app already routes ~87% of its colour through CSS custom properties
   (811 var() references in CSS, 822 in JS). So this layer does two things:

     1. Declares the Signal 3.0 tokens — the real design language.
     2. RE-MAPS every legacy token name onto them.

   The re-map is the point. `--glow-md` still exists, and still resolves —
   to `none`. `--glass` resolves to no blur. `--bg` resolves to rice paper
   instead of near-black. Nothing breaks, and every component that was
   already disciplined about tokens inverts correctly without being touched.
   The alternative — rewriting four thousand lines of component CSS by hand —
   would have been slower AND less complete, because it would have missed the
   colours that live in JS template strings.

   Loaded AFTER style.css / home.css so these definitions win.
   ══════════════════════════════════════════════════════════════════════ */

:root {
    /* ── Surfaces ──────────────────────────────────────────────────────
       Never pure white. Paper has warmth and a little tooth.            */
    --paper:            #F5F2EC;   /* warm rice paper — the page          */
    --paper-ash:        #ECE7DF;   /* soft ash — recessed areas           */
    --paper-raised:     #F8F6F2;   /* surface — barely above the page     */

    /* ── Ink ───────────────────────────────────────────────────────────
       Never pure black. Ink on paper is warm and slightly grey.         */
    --ink:              #1D1C1A;
    --ink-soft:         #66615A;
    --ink-faint:        #AAA49C;
    --rule:             rgba(0, 0, 0, 0.06);   /* almost invisible        */

    /* ── Accent — Yōtei Gold ───────────────────────────────────────────
       Current selection, active nav, primary action, the one number that
       matters. Precious by scarcity: if it is everywhere it is nowhere.  */
    --gold:             #B89B63;
    --gold-rgb:         184, 155, 99;
    --gold-wash:        rgba(184, 155, 99, 0.10);
    --gold-edge:        rgba(184, 155, 99, 0.28);

    /* ── Status — muted naturals, never signal-bright ──────────────────*/
    --olive:            #68745A;   /* success  */
    --amber-burnt:      #AF8452;   /* warning  */
    --vermillion:       #913D32;   /* danger   */
    --slate:            #65727D;   /* info — deliberately not blue       */
    --olive-wash:       rgba(104, 116, 90, 0.10);
    --amber-wash:       rgba(175, 132, 82, 0.10);
    --vermillion-wash:  rgba(145, 61, 50, 0.09);
    --slate-wash:       rgba(101, 114, 125, 0.10);

    /* ── Type ──────────────────────────────────────────────────────────
       Serif for headings (a Japanese art book, not a tech site), a modern
       sans for body, and the same sans for numerals so figures stay clean
       and tabular. Vietnamese is covered by the Latin faces; CJK falls
       back to whichever Song/Ming face the machine has.                  */
    --font-display: 'Cormorant Garamond', 'Songti SC', 'Source Han Serif SC',
                    'Noto Serif', 'Hiragino Mincho ProN', Georgia, serif;
    --font-body:    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
                    'PingFang SC', 'Hiragino Sans GB', sans-serif;
    --font-number:  'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

    /* Editorial scale. Large steps between levels, so hierarchy comes from
       size and space rather than from weight and colour. */
    --t-display:    2.75rem;
    --t-h1:         2rem;
    --t-h2:         1.5rem;
    --t-h3:         1.125rem;
    --t-body:       0.9375rem;
    --t-small:      0.8125rem;
    --t-micro:      0.6875rem;

    --lh-tight:     1.25;   /* display only */
    --lh-normal:    1.6;
    --lh-loose:     1.75;   /* long-form reading                          */
    --ls-display:   -0.01em;
    --ls-body:      0.005em;
    --ls-label:     0.08em; /* small caps labels — the museum placard      */

    /* ── Space ─────────────────────────────────────────────────────────
       Hierarchy is built here, not with shadows. Generous by default.    */
    --s-1:  4px;   --s-2:  8px;   --s-3: 12px;  --s-4: 16px;
    --s-5: 24px;   --s-6: 32px;   --s-7: 48px;  --s-8: 64px;
    --s-9: 96px;   --s-10: 128px;
    --measure: 68ch;                /* comfortable line length            */

    /* ── Form ──────────────────────────────────────────────────────────
       Paper layers, not floating windows. Corners nearly square: rounding
       reads as "app chrome", and this should read as print.              */
    --radius:       3px;
    --radius-lg:    4px;

    /* ── Motion ────────────────────────────────────────────────────────
       Opacity and small movement. Nothing bounces, nothing springs.      */
    --ease:         cubic-bezier(0.4, 0.0, 0.2, 1);
    --dur-fast:     150ms;
    --dur:          220ms;
    --dur-page:     400ms;

    /* ── Marks ─────────────────────────────────────────────────────────
       The same line vocabulary as icons.js, as data-URI masks so CSS
       ::before pseudo-elements can use them. Masks rather than background
       images so the shape inherits colour from `background-color` and
       follows the theme instead of being baked in.                      */
    --mark-report:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.6 2.4h6.2L12.4 5v8.6H3.6z'/%3E%3Cpath d='M9.6 2.4V5h2.8'/%3E%3Cpath d='M5.8 8.4h4.4M5.8 10.6h3'/%3E%3C/svg%3E");
    --mark-revenue: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='8' cy='8' r='5.4'/%3E%3Cpath d='M8 5.1v5.8M6.2 6.6h3.6M6.2 9.4h3.6'/%3E%3C/svg%3E");
    --mark-growth:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 11.4 6 7.2l2.6 2.4L14 4.2'/%3E%3Cpath d='M10.4 4.2H14v3.5'/%3E%3C/svg%3E");
    --mark-target:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.25'%3E%3Ccircle cx='8' cy='8' r='5.4'/%3E%3Ccircle cx='8' cy='8' r='2.2'/%3E%3C/svg%3E");
    --mark-peak:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.25' stroke-linejoin='round'%3E%3Cpath d='M1.8 12.6 6.4 4.6l2.8 4.4 1.8-2.6 3.2 6.2z'/%3E%3C/svg%3E");
}

/* ═══════════════════════════════════════════════════════════════════════
   LEGACY REMAP — every old token, pointed at the new language.
   Ordered to mirror the original :root so the mapping stays auditable.
   ═══════════════════════════════════════════════════════════════════════ */
:root {
    --bg:           var(--paper);
    --bg-card:      var(--paper-raised);
    --bg-hover:     var(--paper-ash);
    --bg-glass:     var(--paper-raised);   /* opaque — glass is gone      */
    --border:       var(--rule);
    --text:         var(--ink);
    --text-muted:   var(--ink-soft);
    --text-dim:     var(--ink-faint);

    /* The old palette was neon by design. Each name now resolves to its
       closest quiet natural, so existing markup reads correctly without
       edits — `.text-cyan` becomes gold, `.badge-red` becomes vermillion. */
    --cyan:         var(--gold);
    --cyan-soft:    var(--gold-wash);
    --cyan-glow:    var(--gold-edge);
    --violet:       var(--slate);
    --violet-soft:  var(--slate-wash);
    --magenta:      var(--vermillion);
    --magenta-soft: var(--vermillion-wash);
    --green:        var(--olive);
    --green-soft:   var(--olive-wash);
    --amber:        var(--amber-burnt);
    --amber-soft:   var(--amber-wash);
    --red:          var(--vermillion);
    --red-soft:     var(--vermillion-wash);
    --shopee:       var(--amber-burnt);
    --shopee-soft:  var(--amber-wash);
    --shopee-glow:  transparent;

    --glass:        none;
    --accent-rgb:   var(--gold-rgb);
}

/* Derived accent values, and the glows — all neutralised. `box-shadow:
   var(--glow-md)` still parses; it simply draws nothing. */
body,
#ws-reports[data-brand-theme],
#ws-data[data-brand-theme],
#ws-admin[data-brand-theme] {
    --accent:       rgb(var(--accent-rgb));
    --accent-soft:  rgba(var(--accent-rgb), 0.10);
    --accent-glow:  rgba(var(--accent-rgb), 0.24);
    --border-glow:  var(--rule);
    --glow-sm:      none;
    --glow-md:      none;
    --glow-card:    none;
}

/* Brand themes stay a product feature, but every hue is pulled down to a
   natural pigment. They read as different inks, not different neons. */
#ws-reports[data-brand-theme="cyan"],    #ws-data[data-brand-theme="cyan"],    #ws-admin[data-brand-theme="cyan"]    { --accent-rgb: 184, 155,  99; }
#ws-reports[data-brand-theme="magenta"], #ws-data[data-brand-theme="magenta"], #ws-admin[data-brand-theme="magenta"] { --accent-rgb: 145,  61,  50; }
#ws-reports[data-brand-theme="amber"],   #ws-data[data-brand-theme="amber"],   #ws-admin[data-brand-theme="amber"]   { --accent-rgb: 175, 132,  82; }
#ws-reports[data-brand-theme="green"],   #ws-data[data-brand-theme="green"],   #ws-admin[data-brand-theme="green"]   { --accent-rgb: 104, 116,  90; }
#ws-reports[data-brand-theme="violet"],  #ws-data[data-brand-theme="violet"],  #ws-admin[data-brand-theme="violet"]  { --accent-rgb: 101, 114, 125; }
#ws-reports[data-brand-theme="coral"],   #ws-data[data-brand-theme="coral"],   #ws-admin[data-brand-theme="coral"]   { --accent-rgb: 166, 106,  84; }

/* ═══════════════════════════════════════════════════════════════════════
   PAGE
   ═══════════════════════════════════════════════════════════════════════ */

body {
    font-family: var(--font-body);
    font-size: var(--t-body);
    line-height: var(--lh-normal);
    letter-spacing: var(--ls-body);
    color: var(--ink);
    background-color: var(--paper);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Paper grain. Two barely-there layers: a fibre speckle and a slow wash of
   light across the page. Felt, not seen — at these alphas the texture reads
   as "this surface is a material" without ever resolving into a pattern. */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    opacity: 0.5;
    background-image:
        radial-gradient(circle at 18% 12%, rgba(255,255,255,0.55) 0%, transparent 42%),
        radial-gradient(circle at 82% 78%, rgba(184,155,99,0.05) 0%, transparent 46%),
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.035'/%3E%3C/svg%3E");
}
body > * { position: relative; z-index: 1; }

/* ═══════════════════════════════════════════════════════════════════════
   TYPE
   ═══════════════════════════════════════════════════════════════════════ */

h1, h2, h3, h4 {
    font-family: var(--font-display);
    font-weight: 500;              /* serif at semibold looks shouted     */
    line-height: var(--lh-tight);
    letter-spacing: var(--ls-display);
    color: var(--ink);
}
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); font-weight: 600; }

p { max-width: var(--measure); line-height: var(--lh-loose); }

/* Figures are the hero of a data product: clean sans, tabular so columns of
   numbers line up, and never italic. */
.num, .ads-big, .kpi-value, .stat-value, .big-number,
td.num, .metric-value {
    font-family: var(--font-number);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.015em;
    color: var(--ink);
}

/* The museum placard: small, spaced, quiet. Used for field labels and
   section eyebrows. */
.label, .tile-head .name, .section-eyebrow, .field-label {
    font-family: var(--font-body);
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-soft);
}

/* ═══════════════════════════════════════════════════════════════════════
   MATERIAL — flatten what the old theme lifted off the page
   ═══════════════════════════════════════════════════════════════════════ */

/* Blanket removal of the previous depth vocabulary. Anything that genuinely
   needs separation gets it from space or a hairline rule, below. */
.card, .home-card, .ads-card, .panel, .box, .modal, .dialog,
.dropdown, .popover, .tooltip, section, aside {
    box-shadow: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    text-shadow: none;
}

.card, .home-card, .ads-card, .panel, .box {
    background: var(--paper-raised);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    padding: var(--s-5);
}

/* Dividers are hairlines, never bars. */
hr, .divider { border: 0; border-top: 1px solid var(--rule); margin: var(--s-6) 0; }

/* ═══════════════════════════════════════════════════════════════════════
   CONTROLS
   ═══════════════════════════════════════════════════════════════════════ */

button, .btn {
    font-family: var(--font-body);
    font-size: var(--t-small);
    font-weight: 500;
    letter-spacing: 0.01em;
    border-radius: var(--radius);
    border: 1px solid var(--rule);
    background: transparent;
    color: var(--ink);
    padding: var(--s-2) var(--s-4);
    box-shadow: none;
    transition: background-color var(--dur) var(--ease),
                border-color var(--dur) var(--ease),
                opacity var(--dur) var(--ease);
}
button:hover, .btn:hover { background: var(--paper-ash); }
button:active, .btn:active { opacity: 0.85; }

/* The one loud element in the system, and it is still not loud. */
.btn-primary, button.primary {
    background: var(--gold);
    border-color: var(--gold);
    color: #FBF9F5;
}
.btn-primary:hover, button.primary:hover { background: #A98D58; border-color: #A98D58; }

input, select, textarea {
    font-family: var(--font-body);
    font-size: var(--t-body);
    color: var(--ink);
    background: var(--paper-raised);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    padding: var(--s-3) var(--s-4);
    transition: border-color var(--dur) var(--ease);
}
input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--gold-edge);
}
input::placeholder, textarea::placeholder { color: var(--ink-faint); }

/* ═══════════════════════════════════════════════════════════════════════
   TABLES — readability first, gridlines last
   ═══════════════════════════════════════════════════════════════════════ */

table { border-collapse: collapse; width: 100%; font-size: var(--t-small); }
th {
    font-family: var(--font-body);
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-soft);
    text-align: left;
    padding: var(--s-3) var(--s-4);
    border-bottom: 1px solid var(--rule);
    background: transparent;
}
td {
    padding: var(--s-3) var(--s-4);
    border-bottom: 1px solid var(--rule);
    color: var(--ink);
}
tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: rgba(0, 0, 0, 0.015); }
/* Zebra striping, if a table insists on it, at the edge of perception. */
tbody tr:nth-child(even) { background: rgba(0, 0, 0, 0.008); }

/* ═══════════════════════════════════════════════════════════════════════
   NAVIGATION — present, never dominant
   ═══════════════════════════════════════════════════════════════════════ */

nav a, .nav-item, .tab {
    font-size: var(--t-small);
    font-weight: 500;
    color: var(--ink-soft);
    border-radius: var(--radius);
    transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
nav a:hover, .nav-item:hover, .tab:hover { color: var(--ink); background: var(--paper-ash); }
/* Active state is a hairline and a colour — no pill, no fill. */
nav a.active, .nav-item.active, .tab.active {
    color: var(--ink);
    background: transparent;
    box-shadow: inset 0 -1px 0 0 var(--gold);
}

/* ═══════════════════════════════════════════════════════════════════════
   MOTION
   ═══════════════════════════════════════════════════════════════════════ */

@keyframes signal-enter {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: none; }
}
.workspace.active, .page-enter { animation: signal-enter var(--dur-page) var(--ease); }

/* Anything the old theme animated by pulsing or glowing simply stops. */
.pulse, .glow, .blink, .shimmer { animation: none !important; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════
   DATA VISUALISATION — the chart is secondary to the number
   ═══════════════════════════════════════════════════════════════════════ */

:root {
    /* Series colours: pigments, in a fixed order. Assigned by identity,
       never cycled, never by rank. */
    --series-1: #B89B63;   /* gold       */
    --series-2: #65727D;   /* slate      */
    --series-3: #68745A;   /* olive      */
    --series-4: #A66A54;   /* clay       */
    --series-5: #8C8478;   /* stone      */
    --series-6: #913D32;   /* vermillion */
    --grid:     rgba(0, 0, 0, 0.05);
    --axis:     rgba(0, 0, 0, 0.16);
}
svg .grid line, svg .grid path { stroke: var(--grid); }
svg .axis line, svg .axis path { stroke: var(--axis); }
svg text { font-family: var(--font-body); font-size: 11px; fill: var(--ink-soft); }

/* ═══════════════════════════════════════════════════════════════════════
   LOGIN — the first impression, so it states the language plainly
   ═══════════════════════════════════════════════════════════════════════ */

#login-screen { gap: var(--s-7); }
#login-screen .logo {
    width: 56px; height: 56px;
    border-radius: var(--radius);
    /* The logo is a raster: a saturated 3D gem on a solid black plate — the
       one asset most at odds with this palette, and desaturating alone leaves
       the plate. Inverting flips it to a dark mark on white, so the plate
       dissolves into the paper and the gem reads as an ink stamp. A proper
       single-colour mark should replace this eventually; until then the
       filter is doing real work, not decoration. */
    filter: invert(1) saturate(0) contrast(1.05) brightness(0.95);
    mix-blend-mode: multiply;
    opacity: 0.85;
}
.login-brand { gap: var(--s-5); margin-bottom: 0; }
.login-divider { height: 44px; background: var(--rule); }

.login-title {
    font-family: var(--font-body);
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-soft);
}
/* The wordmark. Serif, generous, still — the animated rainbow gradient it
   replaces was the single loudest element in the product. */
.login-signal {
    font-family: var(--font-display);
    font-size: 2.5rem;
    font-weight: 400;
    letter-spacing: 0.005em;
    line-height: 1.1;
    color: var(--ink);
    background: none;
    -webkit-text-fill-color: currentColor;
    animation: none;
    padding-bottom: 0;
}
.login-subtitle {
    font-family: var(--font-body);
    font-size: var(--t-micro);
    font-weight: 400;
    letter-spacing: 0.04em;
    color: var(--ink-faint);
    margin-top: var(--s-1);
}

.login-fields { display: flex; flex-direction: column; gap: var(--s-3); width: 320px; }
#login-form input {
    width: 100%;
    padding: var(--s-3) var(--s-4);
    background: transparent;
    /* Underline only: a boxed field on paper reads as a form to be processed;
       a rule reads as a line to be written on. */
    border: 0;
    border-bottom: 1px solid var(--rule);
    border-radius: 0;
    color: var(--ink);
    font-size: var(--t-body);
    text-align: center;
    transition: border-color var(--dur) var(--ease);
}
#login-form input:focus { border-bottom-color: var(--gold); box-shadow: none; }
#login-form button {
    width: 100%;
    margin-top: var(--s-4);
    padding: var(--s-3) var(--s-4);
    background: var(--gold);
    color: #FBF9F5;
    border: 1px solid var(--gold);
    border-radius: var(--radius);
    font-weight: 500;
    font-size: var(--t-small);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    cursor: pointer;
}
#login-form button:hover { background: #A98D58; border-color: #A98D58; }

.login-powered {
    font-size: var(--t-micro);
    letter-spacing: var(--ls-label);
    color: var(--ink-faint);
    margin-top: 0;
}
#login-error {
    color: var(--vermillion);
    font-size: var(--t-small);
    font-weight: 500;
    text-align: center;
    max-width: 320px;
    min-height: 20px;
}

/* ═══════════════════════════════════════════════════════════════════════
   HEADER — the masthead of a publication, not a toolbar
   ═══════════════════════════════════════════════════════════════════════ */

header {
    height: 68px;
    padding: 0 var(--s-6);
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    backdrop-filter: none;
    box-shadow: none;
}
/* The header uses logo-sm.png — a SECOND raster, same treatment. Both assets
   are a saturated gem on a solid black plate; inverting flips the plate to
   white so it dissolves into the paper and the gem reads as an ink stamp. */
header .logo, .header-logo, header img.logo,
.header-identity .logo-sm, img.logo-sm {
    filter: invert(1) saturate(0) contrast(1.05) brightness(0.95);
    mix-blend-mode: multiply;
    opacity: 0.8;
    border-radius: var(--radius);
}
.header-brand-name, .header-title {
    font-family: var(--font-body);
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-soft);
}
/* The animated five-colour gradient was the loudest thing in the product and
   ran forever. A serif wordmark in ink says the same thing once. */
.header-product-name {
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    background: none;
    -webkit-text-fill-color: currentColor;
    color: var(--ink);
    animation: none;
    padding-bottom: 0;
}

/* Brand switcher: a label and a name, not a tinted capsule. */
.brand-zone {
    padding: var(--s-2) 0;
    border: 0;
    background: transparent;
    border-radius: 0;
    gap: var(--s-3);
}
.brand-zone:hover { background: transparent; border: 0; }
.brand-zone .label, .brand-zone > span:first-child {
    color: var(--ink-faint);
}
.brand-switcher-select {
    color: var(--ink) !important;
    font-family: var(--font-body);
    font-size: var(--t-small);
    font-weight: 500;
    letter-spacing: var(--ls-body);
}
.brand-switcher-select option { background: var(--paper-raised); color: var(--ink); }
/* The indicator was a glowing neon dot; now it is a small pigment mark. */
.brand-indicator {
    box-shadow: none !important;
    width: 6px; height: 6px;
    background: var(--gold) !important;
}

/* Presence: a quiet mark that does not breathe. */
.online-dot, .dot.green {
    background: var(--olive) !important;
    box-shadow: none !important;
    animation: none !important;
    width: 6px; height: 6px;
}
.dot.red    { background: var(--vermillion) !important; box-shadow: none !important; }
.dot.yellow { background: var(--amber-burnt) !important; box-shadow: none !important; }
.dot.gray   { background: var(--ink-faint) !important; box-shadow: none !important; }

/* "Axioma OS" — a masthead kicker, not a highlight. */
.header-app-name {
    font-family: var(--font-body);
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-soft);
}

/* Workspace pills → editorial tabs. Active is a rule beneath the word: a
   capsule with a tinted fill and a glow is the single most "SaaS" gesture in
   the old theme. */
.ws-pills { gap: var(--s-5); }
.ws-pills .ws-pill {
    padding: var(--s-2) 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    font-size: var(--t-small);
    font-weight: 500;
    letter-spacing: var(--ls-body);
    color: var(--ink-soft);
    transition: color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ws-pills .ws-pill:hover { border: 0; color: var(--ink); }
.ws-pills .ws-pill.active {
    background: transparent;
    border: 0;
    color: var(--ink);
    box-shadow: inset 0 -1px 0 0 var(--gold);
}

.nav-tab {
    font-size: var(--t-small);
    font-weight: 500;
    color: var(--ink-soft);
    border-bottom: 1px solid transparent;
}
.nav-tab:hover { color: var(--ink); }
.nav-tab.active {
    color: var(--ink);
    border-bottom-color: var(--gold);
    font-weight: 500;
}

/* ═══════════════════════════════════════════════════════════════════════
   SECTION HEADINGS — gold is precious; headings are not the place for it
   ═══════════════════════════════════════════════════════════════════════ */

.card-title, .section-title, .panel-title,
.setup-card .card-title, .readiness-panel .card-title,
.home-card h2, .home-card h3 {
    font-family: var(--font-body);
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: var(--s-5);
}

/* ═══════════════════════════════════════════════════════════════════════
   DIALOGS — "like opening a page, not opening a popup"
   ═══════════════════════════════════════════════════════════════════════
   The `sg-` prefix marks the Signal 3.0 component vocabulary. Components
   that used to carry inline styles adopt these classes, which is the only
   way a stylesheet can reach them at all — an inline rule outranks every
   selector we could write.                                                */

.sg-overlay {
    position: fixed; inset: 0; z-index: 9999;
    display: flex; align-items: center; justify-content: center;
    padding: var(--s-5);
    /* A warm paper veil, not a black scrim. The 55% black this replaces was
       near-invisible on the old dark theme and became a grey shroud over the
       whole page the moment the background turned to paper. */
    background: rgba(245, 242, 236, 0.86);
    animation: signal-enter var(--dur) var(--ease);
}

.sg-dialog {
    width: 100%; max-width: 460px;
    padding: var(--s-6);
    background: var(--paper-raised);
    border: 1px solid var(--rule);
    border-radius: var(--radius-lg);
    box-shadow: none;
    color: var(--ink);
    opacity: 0;
    transform: translateY(6px);
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.sg-dialog.is-open { opacity: 1; transform: none; }

.sg-dialog-head {
    display: flex; justify-content: space-between; align-items: baseline;
    margin-bottom: var(--s-2);
}
.sg-dialog-title {
    font-family: var(--font-display);
    font-size: var(--t-h3);
    font-weight: 500;
    letter-spacing: var(--ls-display);
    color: var(--ink);
}
.sg-dialog-dismiss {
    font-size: var(--t-small); color: var(--ink-faint); cursor: pointer;
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}
.sg-dialog-dismiss:hover { color: var(--ink-soft); }
.sg-dialog-sub {
    font-size: var(--t-small); color: var(--ink-soft);
    margin-bottom: var(--s-5); max-width: var(--measure);
}
.sg-dialog-actions {
    display: flex; align-items: center; gap: var(--s-4);
    margin-top: var(--s-6);
}

.sg-field-stack { display: flex; flex-direction: column; gap: var(--s-4); }
.sg-field {
    display: block;
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-soft);
}
.sg-field input {
    width: 100%;
    margin-top: var(--s-2);
    padding: var(--s-3) 0;
    background: transparent;
    border: 0; border-bottom: 1px solid var(--rule); border-radius: 0;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: var(--t-body);
    letter-spacing: normal;
    text-transform: none;
    box-sizing: border-box;
}
.sg-field input:focus { outline: none; border-bottom-color: var(--gold); }

.sg-btn-primary {
    padding: var(--s-3) var(--s-5);
    background: var(--gold);
    border: 1px solid var(--gold);
    border-radius: var(--radius);
    color: #FBF9F5;
    font-size: var(--t-small);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    cursor: pointer;
}
.sg-btn-primary:hover { background: #A98D58; border-color: #A98D58; }
.sg-status-error { font-size: var(--t-small); color: var(--vermillion); }

/* ═══════════════════════════════════════════════════════════════════════
   LEGIBILITY RESCUE — white text written for a dark ground
   ═══════════════════════════════════════════════════════════════════════
   Seventeen rules in home.css set text to white or near-white because the
   surface beneath them used to be #0F1219. Those surfaces are now paper, so
   the text is white-on-white: not "off-brief", invisible. Anything that sits
   on a token-driven surface is pulled back to ink here.

   These are corrective, not final. The KPI panel still wants a proper
   editorial pass; this makes it readable in the meantime.               */

.home-kpi-modal,
.home-kpi-modal-title,
.home-kpi-modal-status,
.home-kpi-modal label span,
.home-kpi-secondary,
.kpi-brand-kicker,
.kpi-brand-status {
    color: var(--ink);
    text-shadow: none;
}
.home-kpi-modal-title, .kpi-brand-kicker {
    color: var(--ink-soft);
    font-family: var(--font-body);
    font-weight: 500;
    letter-spacing: var(--ls-label);
}
.home-kpi-modal-status, .kpi-brand-status { color: var(--ink-soft); }
.home-kpi-modal-status.warning, .kpi-brand-status.warning { color: var(--amber-burnt); }
.home-kpi-close { color: var(--ink-faint); }
.home-kpi-close:hover, .home-kpi-secondary:hover { color: var(--ink); }

/* The brand block was a saturated gradient with a glow and a giant 900-weight
   watermark — three of the loudest gestures in the old theme stacked in one
   corner. Now a quiet ash panel with the name set in the display serif. */
.home-kpi-brand-card, .kpi-brand-card {
    background: var(--paper-ash);
    border: 1px solid var(--rule);
    box-shadow: none;
}
.home-kpi-brand-name, .kpi-brand-name {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: 1.5rem;
    color: var(--ink);
    text-shadow: none;
}
/* The watermark was white at 13% on near-black. On paper it reads as a smudge
   at any alpha, so it goes. */
.home-kpi-brand-watermark, .kpi-brand-watermark { display: none; }

/* ═══════════════════════════════════════════════════════════════════════
   ICONS — line marks that sit ON the baseline
   ═══════════════════════════════════════════════════════════════════════ */

.sg-icon {
    display: inline-block;
    vertical-align: -0.125em;    /* optical baseline, not the em box top */
    margin-right: 0.45em;
    color: var(--ink-faint);     /* recessive: the label is the content */
    flex-shrink: 0;
}

/* Card headings in home.css inject their icon through ::before content — a
   money bag on revenue, a trophy, a shopping cart. Full-colour pictograms
   drawn in a consumer-app register, and unreachable from JS since they are
   CSS content rather than markup.
   Replaced with masked line marks: the SVG is a mask, so the shape takes
   `background-color` and therefore inherits the theme like every other
   glyph. Uniform 1.25 stroke, 16-unit grid, same set as icons.js. */
#ws-home .summary-head::before,
#ws-home .gmv-card h2::before,
#ws-home .trend-card h2::before,
#ws-home .ads-card h2::before,
#ws-home .products-card h2::before,
#ws-home .funnel-card h2::before {
    content: "";
    display: inline-block;
    width: 1em; height: 1em;
    margin-right: 0.45em;
    vertical-align: -0.125em;
    background-color: var(--ink-faint);
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-position: center;  mask-position: center;
    -webkit-mask-size: contain;     mask-size: contain;
}
/* report — a sealed sheet */
#ws-home .summary-head::before {
    -webkit-mask-image: var(--mark-report); mask-image: var(--mark-report);
}
/* revenue — a coin's rim with a value bar */
#ws-home .gmv-card h2::before {
    -webkit-mask-image: var(--mark-revenue); mask-image: var(--mark-revenue);
}
/* growth — the line itself, which is what the metric is */
#ws-home .trend-card h2::before {
    -webkit-mask-image: var(--mark-growth); mask-image: var(--mark-growth);
}
#ws-home .ads-card h2::before {
    -webkit-mask-image: var(--mark-target); mask-image: var(--mark-target);
}
#ws-home .products-card h2::before {
    -webkit-mask-image: var(--mark-peak); mask-image: var(--mark-peak);
}
#ws-home .funnel-card h2::before {
    -webkit-mask-image: var(--mark-growth); mask-image: var(--mark-growth);
}
h1 .sg-icon, h2 .sg-icon, h3 .sg-icon,
.card-title .sg-icon, .insight-head .sg-icon { color: var(--ink-soft); }
/* Severity is carried by colour, since the alert mark itself is neutral. */
.sg-icon-alert, .warning .sg-icon, .amber .sg-icon { color: var(--amber-burnt); }
.danger .sg-icon, .red .sg-icon, .error .sg-icon   { color: var(--vermillion); }
.ok .sg-icon, .green .sg-icon, .success .sg-icon   { color: var(--olive); }

/* ═══════════════════════════════════════════════════════════════════════
   STYLE SWITCH — a colophon line, not a settings widget
   ═══════════════════════════════════════════════════════════════════════
   It sits in the footer the way a printer's mark sits on the last page of a
   book: available, unobtrusive, and clearly not part of the content.       */

.app-footer {
    padding: var(--s-6) var(--s-6) var(--s-7);
    border-top: 1px solid var(--rule);
    font-size: var(--t-micro);
    letter-spacing: var(--ls-body);
    color: var(--ink-faint);
    gap: var(--s-4);
}
.app-footer-sep { color: var(--ink-faint); opacity: 0.5; }

.theme-switch { display: inline-flex; align-items: baseline; gap: var(--s-3); }
.theme-switch-label {
    font-size: var(--t-micro);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-faint);
}
.theme-switch-opt {
    padding: 0;
    border: 0;
    background: none;
    border-radius: 0;
    font-family: var(--font-body);
    font-size: var(--t-micro);
    letter-spacing: var(--ls-body);
    color: var(--ink-faint);
    cursor: pointer;
    transition: color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.theme-switch-opt:hover { color: var(--ink-soft); background: none; }
.theme-switch-opt.is-active {
    color: var(--ink);
    box-shadow: inset 0 -1px 0 0 var(--gold);
}

/* ═══════════════════════════════════════════════════════════════════════
   MOBILE — the same language at arm's length
   ═══════════════════════════════════════════════════════════════════════
   mobile.css declares the same token names as desktop, so the re-map at the
   top of this file already inverts the page. What follows is only what a
   phone needs differently: a tighter type scale, larger touch targets, and
   the handful of places mobile.css hardcoded a dark-theme colour.        */

#m-boot { color: var(--ink-faint) !important; }

/* Mobile keeps its own accent variable, --m-accent-rgb, which mobile.css
   sets per brand on <body data-brand-theme>. Its charts read it directly
   (`stroke: rgb(var(--m-accent-rgb))`), which is why the sparkline stayed
   cyan after everything around it turned to paper.
   One value, every brand, matching the desktop rule that Yotei runs a single
   palette. The per-brand selectors are neutralised rather than deleted so
   Cyber City keeps them when this layer is switched off. */
body,
body[data-brand-theme="cyan"],
body[data-brand-theme="magenta"],
body[data-brand-theme="amber"],
body[data-brand-theme="green"],
body[data-brand-theme="violet"],
body[data-brand-theme="coral"] {
    --m-accent-rgb: var(--gold-rgb);
}
/* Chart furniture: the gridlines were #1E2433, a dark-theme grey that reads
   as a hard black rule on paper. */
.m-chart line, .m-spark line, #m-app svg line { stroke: var(--grid); }
#m-app svg text { fill: var(--ink-soft); font-family: var(--font-body); }

.m-header, .m-topbar {
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    backdrop-filter: none;
    box-shadow: none;
}
.m-header-logo, .m-header .m-logo, .m-topbar img, #m-login img {
    filter: invert(1) saturate(0) contrast(1.05) brightness(0.95);
    mix-blend-mode: multiply;
    opacity: 0.8;
    border-radius: var(--radius);
}
/* "Axioma" is a kicker; "Signal" is the wordmark. The gradient on the latter
   was the same animated five-colour band the desktop carried. */
.m-header-brand-name {
    font-family: var(--font-body);
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-soft);
}
.m-header-title {
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    background: none;
    -webkit-text-fill-color: currentColor;
    color: var(--ink);
    animation: none;
}
.m-header-divider { background: var(--rule); }
.m-badge-count {
    background: var(--vermillion);
    color: #FBF9F5;
    box-shadow: none;
}
.m-title, .m-header h1 {
    font-family: var(--font-display);
    font-weight: 500;
    letter-spacing: var(--ls-display);
    color: var(--ink);
}
.m-card, .m-panel, .m-section {
    background: var(--paper-raised);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    box-shadow: none;
}
.m-label, .m-menu-label, .m-caption {
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--ink-soft);
}
.m-value, .m-kpi-value, .m-big {
    font-family: var(--font-number);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.015em;
    color: var(--ink);
}

/* Touch targets stay at 44px even though the visual weight drops. */
.m-lang-btn, .m-logout-btn, .m-tab, .m-btn {
    min-height: 44px;
    border-radius: var(--radius);
    border: 1px solid var(--rule);
    background: transparent;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: var(--t-small);
    box-shadow: none;
}
.m-lang-btn.active, .m-tab.active {
    color: var(--ink);
    border-color: var(--gold-edge);
    background: var(--gold-wash);
}
.m-menu, .m-drawer, .m-sheet {
    background: var(--paper-raised);
    border-left: 1px solid var(--rule);
    box-shadow: none;
}
.m-menu-divider { border-top: 1px solid var(--rule); background: none; }

/* On a phone the switch is a stacked pair, not an inline colophon line. */
#m-theme-switch .theme-switch { flex-direction: column; align-items: stretch; gap: var(--s-2); }
#m-theme-switch .theme-switch-label { display: none; }   /* the menu row already labels it */
#m-theme-switch .theme-switch-opt {
    min-height: 40px;
    padding: var(--s-2) var(--s-3);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    text-align: left;
    font-size: var(--t-small);
    color: var(--ink-soft);
}
#m-theme-switch .theme-switch-opt.is-active {
    color: var(--ink);
    border-color: var(--gold-edge);
    background: var(--gold-wash);
    box-shadow: none;
}

/* ═══════════════════════════════════════════════════════════════════════
   SCROLLBAR — part of the page, not a control
   ═══════════════════════════════════════════════════════════════════════ */

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.10);
    border: 3px solid var(--paper);
    border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.18); }

::selection { background: var(--gold-wash); color: var(--ink); }
