/* Generated by mockup/tools/design-bundles.cjs. Edit core.tokens.css or themes/mandarin.css. */
/* Canonical shared geometry. Themes may not redefine these names. */
:root {
 --text-xs: 0.75rem;
 --text-sm: 0.875rem;
 --text-base: 1rem;
 --text-lg: 1.25rem;
 --text-xl: 1.75rem;
 --space-1: 4px;
 --space-2: 8px;
 --space-3: 12px;
 --space-4: 16px;
 --space-6: 24px;
 --space-8: 32px;
 --space-12: 48px;
 --radius-control: 6px;
 --size-button: 38px;
 --weight-button: var(--weight-bold);
 --size-control-target: 44px;
 --size-header-control: var(--size-control-target);
 --size-rail-control: var(--size-control-target);
 --radius-pill: 999px;
 --motion-fast: 160ms;
 --motion-loading-delay: 250ms;   /* loading text shows only when a route takes longer than this */
 /* Line-height roles. Choose by what the text is, never by a number. */
 --leading-solid: 1;          /* numbers, icons, single-line badges */
 --leading-display: 1.15;     /* hero numbers and display titles */
 --leading-heading: 1.35;     /* titles and section headings */
 --leading-ui: 1.45;          /* buttons, labels, captions, compact UI text */
 --leading-body: 1.6;         /* card and description text */
 --leading-reading: 1.8;      /* Korean long-form reading: article body, deck, analysis */
 --weight-regular: 400;
 --weight-semibold: 600;
 --weight-bold: 700;
 --weight-display: 750;
 --figures-number: tabular-nums lining-nums;   /* number cells: closes, changes, table columns line up digit under digit */
 --radius-round: 50%;
 --stroke-thin: 1px;
 --stroke-emphasis: 2px;
 --stroke-thick: var(--stroke-emphasis);
 --stroke-focus: 3px;
 --space-0: 0;
 --space-half: 2px;
 --space-5: 20px;
 --space-10: 40px;
 --space-16: 64px;
 --space-24: 96px;
 /* Radius scale. Components choose a step; no one-off radius values. */
 --radius-xs: 4px;
 --radius-md: 8px;
 --radius-lg: 12px;
 --radius-xl: 16px;
 --radius-2xl: 24px;
 /* Radius roles. Service CSS (Wagle, Sally, tower) names a role, never a step above (validate-design.cjs
    serviceRadiusRoles): a card, panel or popover is --radius-card, a dialog --dialog-radius, a control (input, menu
    item, inline picture) --radius-control or --button-radius, a chip or round shape --radius-pill/--radius-round,
    and the corner of a chat bubble that points at its speaker --radius-tail. */
 --radius-card: var(--radius-xl);
 --radius-tail: var(--radius-xs);
 /* Chips (control-contract.css .chip): one pill for every short label in every service. */
 --size-chip: 2rem;                 /* an interactive chip's visible height; its hit area still reaches --size-control-target */
 --size-chip-sm: 1.5rem;            /* a read-only chip (a mark, a result): compact, not a target */
 --chip-radius: var(--radius-pill);
 --chip-padding-x: var(--space-3);
 --chip-padding-x-sm: var(--space-2);
 --chip-gap: var(--space-1);        /* between the parts inside one chip */
 --chip-font-size: var(--text-xs);
 --chip-weight: var(--weight-semibold);
 --chip-row-gap: calc(var(--size-control-target) - var(--size-chip));  /* wrapped chip rows: hit areas never overlap */
 /* The site footer (control-contract.css .footer): the Mandarin wordmark at one size in every service. */
 --size-footer-wordmark: 1.5rem;
 --tracking-footer-wordmark: -1.4px;
 /* Space kept clear under the fixed site header when scrolling to an anchor. */
 --scroll-offset: var(--space-24);
 /* Fixed component sizes shared by every product. */
 --size-visually-hidden: 1px;
 --size-avatar-xs: 24px;           /* a face inside a line of text: a mention, a reply-to, a small rail */
 --size-avatar-sm: 36px;
 --size-avatar-md: 40px;
 --size-avatar-lg: 4.5rem;          /* profile header on small screens */
 --size-avatar-xl: 5.5rem;          /* profile header */
 --size-account-popover: 18rem;     /* the header account menu */
 /* Icons: one scale for every inline SVG or mask icon outside the header (header icons use --size-header-icon). */
 --size-icon: 1.25rem;
 --size-icon-sm: 1rem;              /* icon inside a small text control */
 --size-badge-inline: var(--size-icon);  /* a badge picture beside a name */
 --size-checkbox: 1.25rem;
 --weight-heavy: 800;               /* wordmarks */
 --opacity-disabled: .5;            /* disabled or read-only controls */
 --opacity-dim: .55;                /* dimmed content that is not a control: a locked step, a resting loading dot */
 --motion-attention: 1.2s;          /* a one-off attention cue (an alert bell ringing twice) */
 /* Dialogs: one shape for every service dialog; the width is chosen by role. */
 --dialog-width-compact: 30rem;     /* alerts, toasts */
 --dialog-width: 42rem;             /* a conversation or a form */
 --dialog-width-wide: 46rem;        /* a profile */
 --dialog-width-workspace: 76rem;   /* a profile with its editor beside it */
 --dialog-gutter: var(--space-8);   /* space kept around a dialog on small screens */
 --dialog-max-block: 90dvh;
 --dialog-radius: var(--radius-xl);
 /* Breakpoints. Media queries cannot read custom properties, so service CSS may only use these widths
    (max-width:N, or min-width:N+1); mockup/tools/validate-design.cjs enforces it. */
 --breakpoint-narrow: 480px;
 --breakpoint-small: 600px;
 --breakpoint-compact: 700px;
 --breakpoint-medium: 800px;
 --breakpoint-wide: 1100px;
 /* Mandarin layout steps between the shared ones. Mandarin sources name a breakpoint, @media(--breakpoint-small), and
    its bundle builders write the width (design-bundles.cjs resolveMedia), so a width is changed only here. */
 --breakpoint-phablet: 540px;
 --breakpoint-compact-plus: 740px;
 --breakpoint-tablet: 900px;
 --breakpoint-large: 1000px;
 --breakpoint-menu: 1024px;        /* the site header folds its menu */
 --breakpoint-wide-plus: 1150px;
 --breakpoint-xwide: 1550px;
 --weight-medium: 500;
 --button-height: var(--size-button);
 --button-min-width: 24px;
 --button-padding-x: var(--space-3);
 --button-padding-y: var(--space-2);
 --button-radius: var(--radius-control);
 --button-font-size: var(--text-base);
 --button-font-size-small: var(--text-xs);
 --button-weight: var(--weight-button);
 --button-line-height: var(--leading-ui);
 --button-target-height: var(--size-control-target);
 /* Header icons (language, theme, alerts): one size and stroke in every service. */
 --size-header-icon: 20px;
 /* The top of every service page (2026-10-31 user: "상단 주가 나오는 거 나오고 메뉴 두께를 맞춰서 위로 튀는 듯한 느낌은
    없었으면 좋겠어"): the world market indices strip, then the site header, at the same heights in Mandarin, Wagle and
    Sally, so moving between them moves nothing. The strip holds one control row; the header is its own height. */
 --size-market-ticker: calc(var(--button-target-height) + 2 * var(--space-1) + var(--stroke-thin));
 --size-site-header: 78px;
 --market-ticker-duration: 36s;
 --market-ticker-item-width: 19rem;
 /* The strip's pulse: a brand dot that beats while every index was collected normally (closes, not a live feed). */
 --market-pulse-size: var(--space-2);
 --motion-pulse: 1.8s;
 --stroke-icon: 2;
 --button-disabled-opacity: var(--opacity-disabled);
 /* Vertical rhythm roles. Every product (channel, journal, research, Wagle, Sally) uses these, not its own numbers. */
 --gap-tight: var(--space-2);        /* label to value, caption to figure */
 --gap-paragraph: var(--space-4);    /* paragraph to paragraph in reading text (about 1em) */
 --gap-block: var(--space-6);        /* block to block, heading to its body */
 --gap-section: var(--space-12);     /* section to section */
 --inset-card: var(--space-6);       /* inside padding of cards and panels */
 --rhythm-body-leading: var(--leading-body);
 --rhythm-heading-leading: var(--leading-heading);
 --rhythm-text-gap: var(--gap-paragraph);
 --rhythm-content-gap: var(--gap-paragraph);
 --rhythm-section-gap: var(--gap-block);
 --rhythm-action-gap: var(--gap-block);
 --action-group-gap: var(--space-3);
 /* Data table: numeric comparison tables share one contract (labels start, numbers end, tabular figures). */
 --table-cell-block: var(--space-3);        /* vertical cell padding */
 --table-cell-inline: var(--space-4);       /* horizontal cell padding */
 --table-rule: var(--stroke-thin);          /* row separator thickness; colour is --border */
 --table-head-size: var(--text-xs);
 --table-head-weight: var(--weight-semibold);
 --table-head-tracking: var(--tracking-label);
 --table-label-weight: var(--weight-semibold);
 --table-number-weight: var(--weight-medium);
 --table-number-tracking: var(--tracking-normal);
 --table-max-inline: 48rem;               /* readable table width; narrower columns keep numbers near their labels */
 /* Section headings (2026-11-01, user: "B안"): a section opens with a band (a tinted strip, an accent bar at its start,
    an icon plate before the title, a family kicker above it); a rail title opens with a kind glyph (a small rounded
    square) and its count. The colours are the theme's family roles (--family-*); these are the shapes. */
 --band-padding-block: var(--space-4);
 --band-padding-inline: var(--space-5);
 --band-gap: var(--space-4);
 --band-accent-width: var(--space-1);
 --band-radius: var(--radius-lg);
 --band-plate: 2.5rem;
 --band-plate-icon: var(--size-icon);
 --band-plate-radius: var(--radius-md);
 --band-gap-after: var(--space-6);         /* band to the section's body */
 --band-copy-min: 16rem;                   /* below this the band's action wraps under the title */
 --glyph-size: 1.5rem;
 --glyph-icon: 0.875rem;
 --glyph-radius: var(--radius-xs);
 --glyph-gap: var(--space-2);
}
@media(max-width:700px),(any-pointer:coarse){:root{--size-button:var(--size-control-target);--button-min-width:var(--size-control-target)}}
@media(max-width:700px){:root{--gap-section:var(--space-8);--inset-card:var(--space-4)}}

/* Mandarin theme — three layers.
   1. Primitive palette: the ONLY place a color value is written.
   2. Semantic roles (dark default, then light): point at primitives. Screens use these names.
   3. Component roles (buttons, index lines): point at semantic roles.
   Brand: Mandarin orange #F7931E (orange-400). Buttons keep it in both themes with dark ink text.
   Orange used as text on light surfaces steps down to orange-750, the lightest step at 4.5:1 or more on every light surface.
   Contrast for every semantic text/background and control pair is checked by mockup/tools/validate-design.cjs. */

/* 1. Primitive palette */
:root {
  --orange-50: #fef6ed;
  --orange-100: #feecd7;
  --orange-200: #fcd6aa;
  --orange-300: #fab96d;
  --orange-400: #f7931e;
  --orange-500: #d9811a;
  --orange-600: #b76d16;
  --orange-700: #995b13;
  --orange-750: #905612;
  --orange-800: #77470e;
  --orange-900: #54320a;
  --orange-950: #2c1a05;

  --neutral-0: #ffffff;
  --neutral-50: #f5f5f2;
  --neutral-75: #f7f8fa;
  --neutral-100: #e9edf2;
  --neutral-150: #dde3eb;
  --neutral-200: #d9e0e6;
  --neutral-250: #d1dfe8;
  --neutral-300: #b4bbc5;
  --neutral-350: #9aa3af;
  --neutral-400: #8b95a3;
  --neutral-500: #6b7584;
  --neutral-600: #526171;
  --neutral-700: #394858;
  --neutral-750: #343b45;
  --neutral-800: #303740;
  --neutral-850: #22272e;
  --neutral-900: #181c21;
  --neutral-925: #10191d;
  --neutral-950: #101215;
  --neutral-975: #080d12;
  --neutral-990: #17212e;
  --neutral-1000: #000000;

  --red-300: #ff8c98;
  --red-700: #a42b42;
  --red-900: #6f1f1f;
  --blue-300: #8bbcff;
  --blue-700: #285cac;
  --violet-300: #b7a0fb;
  --violet-700: #6741ae;
  --violet-750: #7042ad;
  --teal-300: #6dd7cd;
  --teal-700: #08766c;
  --teal-800: #176c63;
  --gray-300: #c4c9d0;
  --slate-300: #8daabf;
  --slate-800: #25374b;
  --yellow-300: #f4cc66;
  --yellow-800: #866009;
  --pink-300: #f291c1;
  --pink-700: #a52c70;
  --sky-300: #80bfff;
  --sky-700: #215aa4;
  --green-300: #98d779;
  --green-800: #3d6f22;
  --green-850: #1f6f3a;
  --lime-300: #c3e36b;
  --lime-800: #556b10;
  --cyan-300: #5ed0ee;
  --cyan-700: #0b6a86;
  --fuchsia-300: #e59af5;
  --fuchsia-700: #8b2fa0;
  --forest-100: #edf4ef;
  --forest-500: #6e8a76;
  --forest-700: #385248;
  --forest-900: #1b2823;
  /* Chart series (2026-10-24): one colour per market layer so a legend tells every line apart (dash patterns stay). */
  --coral-300: #ff9e6e;
  --coral-700: #a8421a;
  --indigo-300: #a3a6ff;
  --indigo-700: #4b47c2;
  --rose-300: #ff7fa8;
  --rose-700: #a8204f;
  --salmon-300: #f7b6a0;
  --salmon-700: #94452f;
  --ice-300: #b8e6ff;
  --ice-700: #1d6589;
  --plum-300: #d79bd1;
  --plum-700: #7d2f78;
  --gold-300: #ffd23f;
  --gold-700: #7d5c00;
  --ochre-300: #e8b04a;
  --ochre-700: #835400;
  --bronze-300: #d9a066;
  --bronze-700: #7a4f1f;
  --mint-300: #8ff0c8;
  --mint-700: #0f7350;
  --sand-300: #d8cfb8;
  --sand-700: #665d44;
  --jade-300: #6fe0a0;
  --jade-700: #1a7444;
  --flame-300: #ffb35c;
  --flame-700: #9c4e00;
  --wheat-300: #e6d27a;
  --wheat-700: #6f6012;
  --olive-300: #c9cf6a;
  --olive-700: #5a6511;
  --peach-300: #ffc7a1;
  --peach-700: #9b4f28;
  --steel-300: #a9b8c9;
  --steel-700: #4a5c70;
  --aqua-300: #7ee8f0;
  --aqua-700: #0d6873;
  --magenta-300: #ff6ad5;
  --magenta-700: #9c1478;

  --cream-50: #f5f4ef;
  --ink-900: #252b33;
  --ink-700: #444444;
  --ink-600: #333333;
  --ink-950: #111111;
  --rule-300: #cccccc;
  --rule-400: #aaaaaa;
  --rust-800: #9d4108;

  --sage-50: #f6f2eb;
  --sage-75: #faf6eb;
  --sage-100: #eef2e8;
  --sage-150: #e8e8df;
  --sage-200: #e1ebdd;
  --sage-300: #c8d2c5;
  --sage-400: #89b3a4;
  --sage-600: #526758;
  --sage-800: #333f39;
  --sage-850: #344433;
  --sage-900: #304d40;

  /* 똥개미 소원나무 (2026-11-01, #wish): the scene's primitives. The page's own colours are a night's at every hour, so one
     set serves both themes; the roles below (--wish-*) point at them and mockup/scripts/wish-scene.js reads the roles by name. */
  --wishsky-975: #070b16;
  --wishsky-950: #0a1022;
  --wishsky-500: #5a6c9a;
  --wishsky-150: #c8d6ff;
  --wishsky-50: #f3ead0;
  /* the small hours (소원나무 고도화 6): a deeper night */
  --wishsky-990: #04060e;
  /* the hours of the day (2026-11-14 "소원나무 24시간 하늘"): dawn and dusk are staged, the day is plain. By lightness: the sky from
     its top down to the hills, the air's light, the sun's light, the ground, the leaves in shade and in sun, the grass. */
  --wishdawn-900: #1b2a5c;
  --wishdawn-500: #6f78b4;
  --wishdawn-100: #f7c9a2;
  --wishdawn-400: #8fa0d8;
  --wishdawn-200: #ffb062;
  --wishdawn-300: #8fb070;
  --wishdawn-700: #4a7560;
  --wishdawn-250: #dcb058;
  --wishdawn-600: #5d7a50;
  --wishday-800: #1a3c6e;
  --wishday-400: #6aa2dc;
  --wishday-100: #c8e0f2;
  --wishday-50: #e8f1fa;
  --wishday-75: #fff0d0;
  --wishday-700: #54743e;
  --wishday-650: #3f7a3c;
  --wishday-300: #8fc04e;
  --wishday-600: #55863a;
  --wishdusk-900: #231d52;
  --wishdusk-500: #b0567a;
  --wishdusk-200: #f8a25a;
  --wishdusk-450: #6f7fb8;
  --wishdusk-300: #ff8444;
  --wishdusk-400: #7f9f5c;
  --wishdusk-700: #486650;
  --wishdusk-250: #dd8c48;
  --wishdusk-650: #566a44;
  --wishsnow-300: #c4cbe0;
  --wishfall-400: #d9822b;
  --wishpetal-100: #ffe6ea;
  --wishsnow-100: #eef3ff;
  --wishsnow-700: #3a4460;
  --wishwitch-300: #b895ff;
  --wishwitch-500: #7a4ce0;
  --wishopen-300: #ff7a66;
  --wishopen-500: #d93a2e;
  --wishsoil-975: #1a120a;
  --wishsoil-950: #17201c;
  --wishsoil-800: #4a3021;
  --wishsoil-500: #5b5a57;
  --wishsoil-250: #d9c89a;
  --wishleaf-950: #1a4230;
  --wishleaf-900: #1f4d33;
  --wishleaf-800: #24603d;
  --wishleaf-700: #2d7247;
  --wishleaf-400: #7fae4a;
  --wishfruit-950: #5a2400;
  --wishfruit-500: #f08a24;
  --wishlamp-400: #ff9a30;
  --wishlamp-200: #ffc070;
  --wishlamp-100: #ffd27a;
  --wishant-1000: #050505;
  --wishant-975: #1f150d;
  --wishant-950: #24170e;
  --wishant-900: #2a1a10;
  --wishant-875: #2e1c12;
  --wishant-850: #33200f;
  --wishant-700: #5a3418;
  --wishant-600: #6e2f1a;
  --wishant-100: #efe2c6;
  --wishwear-500: #3d4a33;
  --wishpaper-50: #fbf6e8;
  --wishpaper-200: #e6dcc2;
  --wishpaper-600: #6b6255;
  --wishpaper-900: #2b2620;
  --wishstamp-700: #c8321e;
  --wishstamp-650: #2f5fa8;
  --wishstamp-600: #4f7a2c;
  /* v2 (2026-11-01, user: "귤은 떨어지지 않고 색만 바뀐다"): a mandarin's colour follows its close change — Korean quote
     colours, up in the red/orange family, down in the blue family; gold near the upper limit. */
  --wishfruit-300: #ffb460;
  --wishfruit-700: #e2481c;
  --wishgold-100: #fff4c2;
  --wishgold-500: #f6c21c;
  --wishbite-300: #8db4ec;
  --wishbite-700: #2c4fa6;
  --wishstamp-550: #a87400;
  --wishled-950: #04060c;
  --wishled-400: #ffb347;
}

/* 똥개미 소원나무 roles (#wish and the wish card): the scene, the slip and the badge pill. */
:root {
  --wish-sky: var(--wishsky-975);
  --wish-fog: var(--wishsky-950);
  --wish-sky-light: var(--wishsky-500);
  --wish-ground-light: var(--wishsoil-975);
  --wish-moonlight: var(--wishsky-150);
  /* The moon is a mandarin (v2, 2026-11-01 user: no flat white disc): its peel, its glow and the warm light it sheds. */
  --wish-moon: var(--wishfruit-500);
  --wish-moon-glow: var(--wishlamp-400);
  --wish-moon-warm: var(--wishlamp-100);
  --wish-star: var(--neutral-0);
  --wish-ground: var(--wishsoil-950);
  --wish-stone: var(--wishsoil-500);
  --wish-bark: var(--wishsoil-800);
  --wish-rope: var(--wishsoil-250);
  --wish-leaf-1: var(--wishleaf-900);
  --wish-leaf-2: var(--wishleaf-800);
  --wish-leaf-3: var(--wishleaf-700);
  --wish-leaf-4: var(--wishleaf-950);
  --wish-fruit: var(--wishfruit-500);
  --wish-fruit-glow: var(--wishfruit-950);
  --wish-unripe: var(--wishleaf-400);
  --wish-lantern: var(--wishlamp-200);
  --wish-lantern-deep: var(--wishlamp-400);
  --wish-firefly: var(--wishlamp-100);
  /* 시간·계절 (소원나무 고도화 6): what the hour, the season and the day may move. The values here are a summer night — the look
     everything else is measured against; the page sets data-wish-hour / -season / -day on itself and the rules below answer. */
  --wish-horizon: var(--wishsky-975);
  --wish-drift: var(--wishfall-400);
  --wish-drift-kind: none;
  --wish-level-air: 1;
  --wish-level-moon: 1;
  --wish-level-star: 1;
  --wish-level-horizon: 0;
  --wish-level-fly: 1;
  --wish-moon-size: 1;
  /* 24시간 하늘 (2026-11-14, user: "소원나무 24시간 하늘 진행해. 새벽과 해질녘만 따로 연출."): the three hours that are not night, each a
     short list the scene mixes with the night by the clock (wish-scene.js "the sky by the clock"): the sky's three colours
     from its top down to the hills, the air's light and the sun's, the ground, what the leaves read as in shade and in sun,
     the grass; then levels against the night's 1 — the air, the key light, the stars, the glow on the hills, the fireflies
     (of the season's), the lamps and halos, the mist, the haze, the shafts, the mandarin's size, and how high the key light
     stands (radians). The top colour is the one the page's light words stand on: keep it deep (4.5:1 under them). */
  --wish-dawn-sky-top: var(--wishdawn-900);
  --wish-dawn-sky-mid: var(--wishdawn-500);
  --wish-dawn-sky-low: var(--wishdawn-100);
  --wish-dawn-sky-light: var(--wishdawn-400);
  --wish-dawn-moon-warm: var(--wishdawn-200);
  --wish-dawn-ground: var(--wishdawn-300);
  --wish-dawn-leaf: var(--wishdawn-700);
  --wish-dawn-leaf-sun: var(--wishdawn-250);
  --wish-dawn-grass: var(--wishdawn-600);
  --wish-dawn-level-air: 1.1;
  --wish-dawn-level-moon: 2;
  --wish-dawn-level-star: 0.25;
  --wish-dawn-level-horizon: 0.45;
  --wish-dawn-level-fly: 0.3;
  --wish-dawn-level-lamp: 0.7;
  --wish-dawn-level-bloom: 0.45;
  --wish-dawn-level-mist: 2;
  --wish-dawn-level-fog: 0.8;
  --wish-dawn-level-shaft: 1.4;
  --wish-dawn-level-orb: 1.15;
  --wish-dawn-level-key: 0.24;
  --wish-dawn-level-ant: 0.8;
  --wish-dawn-level-antrim: 0.9;
  --wish-dawn-level-antlit: 0.9;
  --wish-dawn-level-capcore: 0.25;
  --wish-dawn-cap-key: var(--wishdawn-100);
  --wish-dawn-cap-rim: var(--wishdawn-200);
  --wish-dawn-cap-fill: var(--wishdawn-400);
  --wish-dawn-cap-low: var(--wishant-950);
  --wish-day-sky-top: var(--wishday-800);
  --wish-day-sky-mid: var(--wishday-400);
  --wish-day-sky-low: var(--wishday-100);
  --wish-day-sky-light: var(--wishday-50);
  --wish-day-moon-warm: var(--wishday-75);
  --wish-day-ground: var(--wishday-700);
  --wish-day-leaf: var(--wishday-650);
  --wish-day-leaf-sun: var(--wishday-300);
  --wish-day-grass: var(--wishday-600);
  --wish-day-level-air: 1.8;
  --wish-day-level-moon: 1.4;
  --wish-day-level-star: 0;
  --wish-day-level-horizon: 0.25;
  --wish-day-level-fly: 0;
  --wish-day-level-lamp: 0.1;
  --wish-day-level-bloom: 0.25;
  --wish-day-level-mist: 0.2;
  --wish-day-level-fog: 0.5;
  --wish-day-level-shaft: 0.3;
  --wish-day-level-orb: 0.9;
  --wish-day-level-key: 0.95;
  --wish-day-level-ant: 0.3;
  --wish-day-level-antrim: 0.3;
  --wish-day-level-antlit: 0.62;
  --wish-day-level-caplit: 0.95;
  --wish-day-level-caprim: 0.85;
  --wish-day-level-capcore: 0.5;
  --wish-day-cap-key: var(--wishday-75);
  --wish-day-cap-rim: var(--wishfruit-300);
  --wish-day-cap-fill: var(--wishday-400);
  --wish-day-cap-low: var(--wishant-900);
  --wish-dusk-sky-top: var(--wishdusk-900);
  --wish-dusk-sky-mid: var(--wishdusk-500);
  --wish-dusk-sky-low: var(--wishdusk-200);
  --wish-dusk-sky-light: var(--wishdusk-450);
  --wish-dusk-moon-warm: var(--wishdusk-300);
  --wish-dusk-ground: var(--wishdusk-400);
  --wish-dusk-leaf: var(--wishdusk-700);
  --wish-dusk-leaf-sun: var(--wishdusk-250);
  --wish-dusk-grass: var(--wishdusk-650);
  --wish-dusk-level-air: 1;
  --wish-dusk-level-moon: 1.9;
  --wish-dusk-level-star: 0.35;
  --wish-dusk-level-horizon: 0.5;
  --wish-dusk-level-fly: 0.6;
  --wish-dusk-level-lamp: 0.95;
  --wish-dusk-level-bloom: 0.6;
  --wish-dusk-level-mist: 0.7;
  --wish-dusk-level-fog: 0.8;
  --wish-dusk-level-shaft: 1.3;
  --wish-dusk-level-orb: 1.15;
  --wish-dusk-level-key: 0.2;
  --wish-dusk-level-ant: 0.8;
  --wish-dusk-level-antrim: 1;
  --wish-dusk-level-antlit: 0.85;
  --wish-dusk-level-capcore: 0.2;
  --wish-dusk-cap-key: var(--wishdusk-200);
  --wish-dusk-cap-rim: var(--wishdusk-300);
  --wish-dusk-cap-fill: var(--wishdusk-450);
  --wish-dusk-cap-low: var(--wishant-975);
  --wish-ant-1: var(--wishant-900);
  --wish-ant-2: var(--wishant-850);
  --wish-ant-3: var(--wishant-950);
  --wish-ant-4: var(--wishant-875);
  --wish-ant-5: var(--wishant-975);
  --wish-ant-me: var(--wishant-600);
  --wish-ant-eye: var(--wishant-1000);
  --wish-ant-white: var(--wishant-100);
  --wish-ant-iris: var(--wishfruit-500);
  --wish-ant-mouth: var(--wishant-975);
  --wish-ant-iris-glow: 0.5;
  --wish-ant-glow: var(--wishlamp-400);
  --wish-ant-rim: 0.7;
  --wish-ant-tongue: var(--wishfruit-700);
  /* my ant's light (2026-11-14): the picture of a lit ball its shell is read from — light from above, a tangerine rim, a blue fill, dark underneath; an hour's own below its levels */
  --wish-cap-key: var(--wishlamp-100);
  --wish-cap-rim: var(--wishlamp-400);
  --wish-cap-fill: var(--wishbite-700);
  --wish-cap-low: var(--wishant-975);
  --wish-wear-tin: var(--wishwear-500);
  --wish-wear-leaf: var(--wishleaf-700);
  --wish-wear-cloth: var(--wishfruit-500);
  --wish-wear-wire: var(--wishlamp-200);
  --wish-paper: var(--wishpaper-50);
  --wish-paper-edge: var(--wishpaper-200);
  --wish-ink: var(--wishpaper-900);
  --wish-ink-muted: var(--wishpaper-600);
  --wish-stamp-ripe: var(--wishstamp-700);
  --wish-stamp-flat: var(--wishstamp-600);
  --wish-scrim: color-mix(in srgb, var(--wishsky-975) 80%, transparent);
  /* v2 grades: ripe deepens from low to high with the rise, 물린 귤 from low to high with the fall, gold near the limit. */
  --wish-ripe-low: var(--wishfruit-300);
  --wish-ripe-high: var(--wishfruit-700);
  --wish-gold: var(--wishgold-500);
  --wish-gold-spark: var(--wishgold-100);
  --wish-bitten-low: var(--wishbite-300);
  --wish-bitten-high: var(--wishbite-700);
  --wish-stamp-gold: var(--wishstamp-550);
  --wish-stamp-bitten: var(--wishstamp-650);
  /* the 전광판 (LED board) over the scene and the glow round the slip I write on */
  --wish-led-bg: var(--wishled-950);
  /* how much of the 전광판's plate is there over the scene: see-through by night; the scene closes it under a bright sky (wish-scene.js skyNow) */
  --wish-led-veil: 58%;
  --wish-led: var(--wishled-400);
  --wish-led-up: var(--wishfruit-700);
  --wish-led-down: var(--wishbite-300);
  --wish-led-rule: color-mix(in srgb, var(--wishled-400) 22%, transparent);
  --wish-aura: color-mix(in srgb, var(--wishlamp-200) 55%, transparent);
  --wish-aura-soft: color-mix(in srgb, var(--wishlamp-200) 22%, transparent);
  --wish-stamp-ink: var(--wishstamp-700);
}

/* Non-color theme geometry */
:root {
  /* 소원나무 (Wagle /wish): the slip, the order form and the stage. */
  --size-wish-slip: 15rem;
  --size-wish-slip-large: 21rem;
  --size-wish-form: 36rem;
  --size-wish-stage-min: 30rem;
  --size-wish-top: 8.25rem;
  --size-wish-hint-x: 50%;
  --size-wish-hint-y: 50%;
  --size-wish-hint-arrow: 0px;
  --size-wish-launcher-room: 5.25rem;
  --size-wish-fade: 4rem;
  --size-wish-fruit: 0.7rem;
  --size-wish-zigzag: 0.6rem;
  --wish-slip-drop: drop-shadow(0 8px 16px var(--overlay-medium));
  /* v2: the slip I write on (centre of the view; a bottom sheet on a phone), its stamp, the LED board and the trade tape */
  --size-wish-compose: 23rem;
  --size-wish-proof: 26rem;
  --size-wish-proof-room: 12rem;
  --size-wish-stamp: 4.5rem;
  --size-wish-led-cell: 7.5rem;
  --size-wish-digit: 1em;
  --size-wish-digit-w: 1ch;
  --size-wish-sheet-max: 92dvh;
  --size-wish-talk: 15rem;
  --size-wish-talk-compact: 12rem;
  --size-wish-tape-slip: 13rem;
  --wish-aura-blur: 28px;
  --wish-aura-spread: 6px;
  --wish-stamp-press: 1.7;
  --wish-fold-scale: 0.08;
  --motion-wish-aura: 2.4s;
  --motion-wish-stamp: 420ms;
  --motion-wish-fold: 650ms;
  --motion-wish-digit: 600ms;
  --motion-wish-ticker: 40s;
  --motion-wish-tape: 60s;
  --page-entry-gap: var(--space-6);
  --page-section-gap: var(--space-6);
  --page-heading-gap: var(--space-2);
  --page-title-size: var(--text-xl);
  --page-menu-title-size: var(--text-title);         /* a menu page's title (kicker and brand dot, page-shell.js) */
  --page-menu-title-size-compact: var(--text-title-sm);
  --page-document-width: 64rem;
  --page-document-padding: calc(var(--space-6) + var(--space-1));
  --page-section-width: calc(var(--page-document-width) - var(--page-document-padding)*2);
  --page-reading-width: 45rem;
  --page-company-image-size: 4rem;
  /* 콤마의 한 장 (2026-10-24): the line-name and ledger columns beside the company's words (a narrower pair under medium). */
  --comma-name-width: 9rem;
  --comma-figures-width: 16rem;
  --comma-name-width-compact: 7rem;
  --comma-figures-width-compact: 13rem;
  /* A company row in a list (ranking, rails, context members, channel links): the 'rank' rendition, 48px. */
  --company-row-thumbnail: var(--space-12);
  /* A company inside a chip row (same context, toast): the small picture. */
  --company-chip-thumbnail: var(--space-6);
  /* An event row (the channel's timeline): the day and the kind keep one column each, so titles start on one edge. */
  --event-row-day: 6.5rem;
  --event-row-kind: 5rem;
  /* 주가의 시간: the 만다린 읽기 column beside the chart (below it on a narrow screen). */
  --channel-price-reading-width: 21rem;
  /* One readout cell of the price chart (a line's name and value on one line). */
  --price-readout-cell: 9.5rem;
  /* The kinds of a company's events (chart markers and their row dots). */
  --event-filing: var(--condition);
  --event-journal: var(--comparison);
  --event-comma: var(--brand);
  --event-earlier: var(--text-secondary);
  --event-toast: var(--text-muted);
  --thread-feed-width: 40rem;
  --thread-side-width: 15rem;
  --thread-composer-height: 3rem;
  --thread-composer-expanded: 7rem;
  --wagle-content-height: calc(var(--size-control-target)*8);
  --thread-image-height: 28rem;
  --workbench-nav-width: 14rem;
  --workbench-gap: var(--space-6);
  --workbench-title-size: var(--text-xl);
  --size-editor-cover: 15rem;
  --motion-menu: 260ms;
  --ease-menu: cubic-bezier(.22,1,.36,1);
  --menu-link-size: var(--text-lg);
  --market-country-height: 28rem;
  --market-stage-height: clamp(28rem,42cqw,38rem);
  --market-stage-mobile-height: clamp(20rem,75cqw,32rem);
  --comparison-stage-mobile-height: clamp(33rem,105cqw,40rem);
  --market-chrome-clearance: 12rem;
  --site-chrome-height: var(--market-chrome-clearance);
  --page-path-leading: var(--leading-body);
  --page-path-size: var(--text-xs);
  --page-path-gap: var(--space-6);
  --account-nav-gap: var(--space-3);
  --account-nav-padding: var(--space-4);
  --graph-height: clamp(690px, 78vh, 860px);
  --graph-height-mobile: clamp(560px, 74vh, 680px);
  --graph-panel-width: 340px;
  /* 만다린 그래프 v1.0 (2026-10-24): the connection map's circles keep these sizes on screen at any zoom (the pick radius
     never grows), lines are styled by source, the panel is a sheet on phones. */
  --graph-node-focus: 9px;
  --graph-node-member: 6px;
  --graph-node-outside: 4.5px;
  --graph-node-group: 13px;
  --graph-group-stack: 3px;
  --graph-sheet-height: 62svh;
  --graph-line-width: 1.4px;
  --graph-line-width-card: 3px;
  --graph-line-width-subject: 3.2px;
  --graph-line-dash-rumor: 2 5;
  --graph-line-opacity: .85;
  --graph-line-opacity-faded: .16;
  --graph-outside-opacity: .55;
  --graph-galaxy-line-opacity: .35;
  --graph-label-halo: 3px;
  --graph-legend-mark: 18px;
  --graph-viewport-offset: 330px;
  --graph-height-min: 460px;
  --size-directory-search: 26rem;
  --size-badge-card: 16rem;
  /* A number or short code typed inside a table row (staff tables). */
  --size-table-field: 8rem;
  /* Google Translate attribution: logo geometry and a white surface are required by the provider, in both themes. */
  --size-attribution-logo-width: 176px;
  --size-attribution-logo-height: 16px;
  /* One face for every service (2026-11-08, user: "만다린 폰트도 프리텐다드가 깔끔하고 가독성 좋던데, 전체를 프리텐다드로"):
     Pretendard Variable, self-hosted in the storage in unicode-range pieces (mockup/tools/build-font.cjs,
     mockup/design/DESIGN_TOKENS_v0.2.md "글꼴"). While a piece downloads (font-display: swap) and for letters it has
     not (Chinese), the device face draws: the same device faces as before, in the same order. */
  --font: "Pretendard Variable", Pretendard, "Malgun Gothic", "Apple SD Gothic Neo", "Noto Sans KR", "Noto Sans CJK KR", system-ui, sans-serif;
  /* Numbers are the same face; a number cell also takes the tabular figures (--figures-number), so closes, changes and
     table columns line up digit under digit. */
  --font-number: var(--font);
  /* The 'mandarin.' letters of the header and footer keep the face they had (the device's UI face): a mark, not reading
     text; kept apart on 2026-11-08 with the report cover's masthead. */
  --font-wordmark: "Segoe UI", system-ui, sans-serif;
  /* Home rails v2 (2026-10-31, user: "디자인 토큰만 제대로 쓰면 존나 멋질 듯함"): each rail its own form. The warning board's
     mono face is a system face (no download; a fixed-width face for codes and the board, Pretendard has none); Hangul falls
     back by the OS. Dot's cover headline is Pretendard too since 2026-11-08 (the serif read apart from every other title),
     set heavy by its rule. */
  --font-mono: "D2Coding", "Cascadia Mono", Consolas, "SF Mono", Menlo, "Noto Sans Mono CJK KR", "Malgun Gothic", "Apple SD Gothic Neo", monospace;
  --font-display: var(--font);
  /* A hand on a slip (소원나무 wish line): installed handwriting faces first, no web font. Kept apart from Pretendard on
     2026-11-08: a wish is a member's own note on the tree, the handwriting is the point. */
  --font-hand: "Nanum Pen Script", "Nanum Brush Script", "NanumPen", "Segoe Print", "Bradley Hand", "Comic Sans MS", cursive;
  /* The movers swarm: a mark's diameter runs min → max by the square root of its volume surge (capped); the ±10% band
     takes --rail-swarm-gap of the axis; the plot is at least --rail-swarm-cross tall across, and on a phone the axis
     stands upright, --rail-swarm-axis long. (2026-11-14, user: "제목에 비해 버블 챠트가 작아져서 눈에 안들어와": the marks 10–26 → 12–34 px, the
     plot 11 → 15rem across, beside the rank card.) */
  --rail-swarm-dot-min: 12px;
  --rail-swarm-dot-max: 34px;
  --rail-swarm-gap: 14%;
  --rail-swarm-cross: 15rem;
  --rail-swarm-axis: 34rem;
  /* The ranking's lanes (2026-10-31 v2): one row per company at a touch target's height, the curve column never narrower
     than --rail-lane-curve-min, a curve's stroke one of five steps by its move, and the dot at each end. */
  --rail-lane-height: calc(var(--rail-lane-thumb) + var(--space-3));   /* at least; a lane fills its share of the panel (level with the board beside it) */
  --rail-lane-height-phone: var(--size-control-target);
  --rail-lane-curve-min: 6rem;
  --rail-lane-stroke-0: 2px;   /* the smallest move (still visible, never a hairline) */
  --rail-lane-stroke-1: 3px;
  --rail-lane-stroke-2: 4px;
  --rail-lane-stroke-3: 5px;
  --rail-lane-stroke-4: 6px;   /* the rail's largest move */
  --rail-lane-dot: 8px;
  --rail-lane-thumb: var(--space-6);
  --rail-lane-pill: 3.5rem;   /* the change pill's column (pills end-aligned, ranks aligned before it) */
  --rail-lane-was: 3.75rem;   /* a phone lane's previous rank and its connector */
  /* Dot's covers: the lead headline and the four beside it. */
  --rail-cover-lead: clamp(1.5rem,2.4vw,2.125rem);
  --rail-cover-title: 1.1875rem;
  --rail-cover-min-height: 15rem;
  /* The decisions calendar's narrowest day. */
  --rail-week-day-min: 8.5rem;
  --size-header-target: calc(var(--size-header-control) - var(--space-1) * 2 - var(--stroke-thin) * 2);
  --size-rail-icon: 20px;
  --space-rail-controls: var(--space-2);
  --content-width: 1440px;
  --operations-content-width: 1280px;
  --operations-header-content-width: 1224px;
  --size-report-reading: 56rem;
  --motion-spinner: 800ms;
  --size-spinner: 1em;
  --text-md: 1.125rem;
  --text-title-sm: 1.5rem;
  --text-title: 2rem;
  --text-display: 2.25rem;
  --text-display-lg: 2.5rem;
  --text-hero: 3rem;
  --text-reading: 1.0625rem;
  --text-fluid-title: clamp(2rem,3.2vw,2.75rem);
  --text-fluid-viewer: clamp(1.4375rem,2.4vw,2.125rem);
  --text-fluid-hero: clamp(2rem,3.1vw,3rem);
  --text-fluid-price: clamp(1.4375rem,2.1vw,2rem);
  --tracking-normal: 0;
  --tracking-label: .1em;
  --tracking-kicker: .12em;
  --tracking-eyebrow: .13em;
  --tracking-wide: .16em;
  --tracking-heading: -.035em;
  --tracking-display: -.055em;
  --tracking-numeric: -1px;
  --tracking-logo: -1.4px;
  --tracking-rank: -2px;
  --z-rail: 19;
  --z-header: 20;
  --z-companion: 21;
  --z-notice: 40;
  --z-skip: 50;
  --z-backdrop: -2;
  --z-decoration: -1;
  --z-raised: 1;      /* a part drawn over its own component's lines */
  --z-sticky: 3;      /* a sticky strip inside the page flow */
  --z-popover: 5;     /* a menu opened from a card */
  /* Wagle play page and community surfaces. */
  --play-left-width: 14rem;
  --play-left-compact-width: 12rem;
  --play-right-width: 17rem;
  --play-broadcast-min-height: 7rem;
  --play-broadcast-height: 10rem;
  --play-broadcast-height-compact: 11rem;
  --size-rank-badge: 3.75rem;
  --size-rank-step: 1.75rem;
  --size-menu-min: 11rem;
  --size-menu-max-block: 16rem;
  --size-copy-min: 8rem;              /* a text column's width before it wraps under its picture */
  --size-panel-min-block: 10rem;      /* a dialog panel's height while its list loads */
  --size-side-editor: 24rem;
  --size-member-drawer: 38rem;
  --size-member-drawer-clearance: 7rem;
  --measure-caption: 30ch;
  /* Staff tables and dashboards. */
  --size-table-field-min: 4.5rem;
  --size-table-number: 6rem;
  --size-tier-image: 2rem;
  --size-dash-card: 12rem;
  --size-search-field: 14rem;
  /* Share card (a 1200x630 picture made on the server by robinhood/src/og.cjs): its own pixel type scale. */
  --share-type-title: 44px;
  --share-type-body: 46px;
  --share-type-label: 30px;
  --share-type-chip: 28px;
  --share-type-tagline: 26px;
  --print-space-2: 2mm;
  --print-space-3: 3mm;
  --print-space-4: 4mm;
  --print-space-5: 5mm;
  --print-space-6: 6mm;
  --print-space-14: 14mm;
  --print-space-16: 16mm;
  --print-type-8-5: 8.5pt;
  --print-type-9: 9pt;
  --print-type-10: 10pt;
  --print-type-10-5: 10.5pt;
  --print-type-11: 11pt;
  --print-type-12: 12pt;
  --print-type-21: 21pt;
}

/* Mandarin component geometry (2026-10-10). mockup/styles write no length, opacity or duration of their own: each
   value is named here once, by the role it plays, and a stylesheet asks for the role (validate-design.cjs). */
:root {
  --motion-slow: 350ms;
  --stroke-accent: 3px;               /* a coloured edge that marks a changed scene */
  --stroke-icon-bold: 3;              /* a play icon drawn over a chart */
  /* Chart strokes, in SVG user units (the chart viewBox), not CSS pixels. */
  --chart-stroke-line: 3;
  --chart-stroke-comparison: 2.5;
  --chart-stroke-marker: 2;
  --chart-stroke-baseline: .8;
  --chart-stroke-grid: .7;
  --chart-stroke-guide: 1;
  --chart-dash-baseline: 4 5;
  --chart-dash-reference: 6 4;       /* the KOSPI reference line under a company flow */
  --chart-dash-grid: 3 7;
  --chart-dash-cursor: 3 5;
  --drawn-juice: var(--orange-400);   /* 손그림: what fills a bucket — mandarin juice on both papers (a mark, never text) */
  --drawn-dash-edge: 4 7;             /* 손그림: the dashed edge of a usual range, in screen pixels (the strokes do not scale) */
  /* Each market index keeps one dash pattern wherever it is drawn (beside its --index-* colour). */
  --index-kospi-dash: 7 3;
  --index-kosdaq-dash: 2 4;
  --index-sp500-dash: 10 4 2 4;
  --index-dow-dash: 16 4;
  --index-nasdaq-dash: 4 1 1 1;
  --index-sox-dash: 8 2 1 2 1 2;
  --index-nikkei225-dash: 12 5;
  --index-shanghai-dash: 3 3;
  --index-dax-dash: 8 3 2 3;
  --index-uk100-dash: 1 5;
  /* Macro layers stacked on the world-market chart (2026-10-20) keep their own dash beside their --layer-* colour. */
  --layer-usdkrw-dash: 6 2 1 2;
  --layer-jpykrw-dash: 5 2 1 2 1 2;
  --layer-eurkrw-dash: 4 4 1 4;
  --layer-cnykrw-dash: 9 2 1 2;
  --layer-usdjpy-dash: 5 3 1 3;
  --layer-eurusd-dash: 12 2 2 2;
  --layer-usdcny-dash: 3 1;
  --layer-gold-dash: 14 3;
  --layer-silver-dash: 4 2;
  --layer-brent-dash: 9 2 2 2;
  --layer-wti-dash: 2 2 8 2;
  --layer-copper-dash: 11 3 3 3;
  --layer-nickel-dash: 6 6;
  --layer-aluminium-dash: 1 3;
  --layer-natgas-dash: 3 2 3 6;
  --layer-wheat-dash: 10 2;
  --layer-corn-dash: 2 6;
  --layer-soybean-dash: 7 2 2 2 2 2;
  --layer-krxgold-dash: 2 3 8 3;
  --layer-gasoline-dash: 6 3;
  --layer-diesel-dash: 2 2;
  --layer-k200fut-dash: 10 3 3 3;
  --layer-vkospi-dash: 1 2;
  --opacity-inactive: .5;             /* a resting carousel dot */
  --opacity-faint: .4;                /* a background line or cursor drawn under content */
  --opacity-backdrop: .23;            /* a picture behind a viewer's text */
  --opacity-trace: .12;               /* a picture behind a chart */
  --offset-skip: 70px;                /* the skip link waits above the page until focused */
  --offset-toast: 28px;
  --offset-menu-bar: 6px;             /* menu icon bars meet in the middle to form a cross */
  --offset-node-fact: 18px;
  --offset-node-compare: 14px;
  --offset-node-condition: var(--space-2);
  --offset-condition-link-x: 18px;
  --offset-condition-link-y: 22px;
  /* Site shell */
  --size-site-header-compact: 70px;
  --size-site-nav-compact: 46px;
  --size-search: 300px;
  --size-dialog-close: 36px;
  --size-toast-max: 90vw;
  --size-scroll-panel: 65vh;          /* a list that scrolls inside the page */
  --size-scroll-panel-compact: 30vh;
  --size-diagnostics: 18rem;
  --size-icon-text: 1em;              /* an icon as tall as its text */
  --size-paper: 900px;                /* a printable document or its preview */
  --size-paper-label: 90px;
  --size-paper-label-narrow: 65px;
  --size-policy-reading: 46rem;
  --size-mobile-preview: 390px;
  --size-studio-nav: 190px;
  --size-studio-nav-compact: 155px;
  --size-report-nav: 260px;
  /* Home */
  --size-hero: 388px;
  --size-hero-medium: 390px;
  --size-hero-compact: 350px;
  --size-hero-narrow: 380px;
  --size-hero-aside: 250px;
  --size-hero-aside-compact: 245px;
  --size-hero-copy: 340px;
  --size-hero-copy-narrow: 250px;
  --size-hero-reading: 40rem;
  --size-featured-hero: 520px;
  --size-featured-hero-compact: 420px;
  --size-featured-context: 260px;
  /* The featured carousel controls (dots and play) at the slide's bottom right: the proof strip stays clear of them. */
  --size-featured-controls: 280px;
  --size-featured-fact-min: 14rem;   /* a proof cell narrower than this goes to its own row, so a filing title is never cut */
  --size-rail-thumb: 38px;
  --size-rail-thumb-compact: 28px;
  --size-rail-copy-min: 38px;
  --size-event-time: 48px;
  --size-rank-content: 96px;
  --size-market-chart: 114px;
  --size-market-chart-max: 320px;
  --size-rank-number: 34px;
  --size-rank-number-compact: 28px;
  --size-context-control: 100px;
  --size-context-heading: 3em;        /* three lines of a scene heading */
  --size-market-session-en: 110px;
  /* Company channel, viewer and Sally */
  --size-channel-card-min: 15rem;
  --size-video-description-max: 20rem;
  --size-insight-badge: 200px;
  --size-change-label-min: 120px;
  --size-change-value-min: 80px;
  --size-pair-image: 125px;
  --size-pair-image-compact: 100px;
  --size-scene-aside: 220px;
  --size-scene-aside-compact: 215px;
  --size-layer-label: 88px;
  --size-layer-label-compact: 66px;
  --size-layer-value: 105px;
  --size-layer-value-compact: 90px;
  --size-time-slider: 28px;
  --size-time-labels: 22px;
  --size-track-label: 80px;
  --size-track-label-narrow: 60px;
  --size-viewer-heading: 650px;
  --size-viewer-reading: 820px;
  --size-viewer-play: 40px;
  --size-viewer-progress: 22px;
  --size-viewer-progress-min: 24px;
  --size-intersection-min: 175px;
  --size-intersection-min-compact: 140px;
  --size-mesh-link: var(--space-8);
  --size-mesh-link-compact: 14px;
  --size-mesh-dot: 5px;
  --size-sally-room: 440px;
  --size-sally-room-max-block: 94dvh;
  --size-sally-portrait: 280px;
  --size-sally-portrait-min: 170px;
  --size-sally-portrait-max: 380px;
  --size-sally-messages: 180px;
  --size-sally-messages-compact: 150px;
  /* Graph */
  --size-graph-select: 240px;
  --size-graph-filter: 130px;
  --size-graph-cluster-label: 170px;
  --size-graph-node-label: 180px;
  --size-graph-hover: 210px;
  --size-graph-label-compact: 120px;
  /* Pricing (#pricing, styles/routes/pricing.css; 2026-10-24 gestalt sequence): a scene's height beside the held
     picture, where the square picture is cropped (desktop column and the phone band), how far the next picture settles
     as it fades in, and the reveal: rise, stagger, the picture change. */
  --pricing-scene-min: 78vh;
  --pricing-shot-focus: 50% 60%;
  --pricing-band-ratio: 16/10;
  --pricing-shot-scale: 1.04;
  --pricing-rise: var(--space-6);
  --motion-reveal: 700ms;
  --motion-stagger: 70ms;
  --motion-shot: 900ms;
  /* 만다린 리포트 표지의 등장 (styles/routes/report-cover.css): the light coming in, then the words in reading order. */
  --motion-cover-light: 1600ms;
  --motion-cover-word: 640ms;
  --motion-cover-lead: 360ms;
  --motion-heart: 1200ms;
  --ease-reveal: var(--ease-menu);
  /* 만다린 프리즘 (#report, styles/routes/report.css; 2026-10-24): the document's page and reading measure, the contents
     bar, the cover title and the one-line conclusion, the stat figures, the colour key of a force, the lock mark. */
  --prism-page: 80rem;
  --prism-measure: 44rem;
  --prism-toc: 13rem;
  /* the connection rail beside an edition (2026-10-31): its width, and the least it keeps before it folds under the text */
  --prism-rail: 18rem;
  --prism-rail-min: 13rem;
  --prism-rays: 16rem;
  --prism-title-size: clamp(2.25rem,4.4vw,3.5rem);
  --prism-title-size-sm: clamp(1.25rem,2.4vw,1.625rem);
  --prism-conclusion-size: clamp(1.125rem,1.8vw,1.375rem);
  --prism-number-size: 2.5rem;
  --prism-stat-size: clamp(1.375rem,2.2vw,1.75rem);
  --prism-stat-min: 10rem;
  --prism-ray-key: .75rem;
  --prism-check-day: 9.5rem;
  --prism-term-width: 12rem;
  --prism-sticky-top: calc(var(--site-chrome-height) + var(--space-6));
  /* 만다린 리포트 표지 (docs/editorial/report-design-system.md, 2026-10-30): the cover plate's shape, the masthead's
     Latin serif (a system face, no download; kept on 2026-11-08 when every other text became Pretendard: the 'mandarin.'
     letters are the mark, not reading text), the title and conclusion sizes on the plate, the art's proportions. */
  --font-masthead: Georgia, "Times New Roman", "Noto Serif", serif;
  /* 만다린 리포트 본문의 활자 (2026-10-30, user: "폰트가 병신 같고 위계도 이상하고 깔끔하지 않다. AIDX는 깔끔한데"): one reading
     face, few sizes, one label style. Since 2026-11-08 the whole service's face (--font) and the same pieces. */
  --font-report: var(--font);
  --report-text: 1rem;
  --report-text-sm: .9375rem;
  --report-text-xs: .8125rem;
  --report-h2: clamp(1.25rem,2vw,1.5rem);
  --report-num: clamp(1.875rem,3.2vw,2.5rem);
  --report-answer: clamp(1.0625rem,1.6vw,1.25rem);
  --report-stat: clamp(1.5rem,2.4vw,1.875rem);
  --report-body-leading: 1.78;
  --report-head-leading: 1.32;
  --report-label-tracking: .04em;
  /* 꿀팁 (2026-11-07, 독자 피드백: 참고서를 보는 느낌): 형광펜 칠한 쪽지. 두 테마 모두 브랜드 색에서 만든다. */
  --report-tip-paper: color-mix(in srgb,var(--brand) 11%,var(--surface-raised));
  --report-tip-edge: color-mix(in srgb,var(--brand) 38%,transparent);
  --report-tip-marker: color-mix(in srgb,var(--brand) 34%,transparent);
  --report-tip-sticker: 2.75rem;
  --report-section-pad: clamp(1.25rem,3vw,2.5rem);
  --report-section-gap: clamp(1.5rem,3vw,2.5rem);
  --report-theory-term: 7.5rem;
  --report-claim-chip: 5rem;
  --report-claim-chip-latin: 9rem;
  --report-claim-chip-han: 6rem;
  --report-claim-air-2: 2em;
  --report-claim-air-3: .5em;
  --report-masthead-size: .8125rem;
  --report-masthead-tracking: .32em;
  --report-masthead-tracking-open: .64em;
  --report-series-size: clamp(.875rem,1.2vw,1rem);
  --report-cover-title: clamp(2.5rem,5.2vw,4.25rem);
  --report-cover-lead: clamp(1.0625rem,1.6vw,1.3125rem);
  --report-cover-number: clamp(1.5rem,2.6vw,2.125rem);
  --report-cover-pad: clamp(1.25rem,3.2vw,2.75rem);
  --report-cover-radius: var(--radius-card);
  --report-cover-art-ratio: 3/2;
  --report-cover-hero-min: clamp(22rem,38vw,32rem);
  --report-cover-lead-measure: 34rem;
  --report-cover-medal: 3.25rem;
  --report-force-swatch: 1.75rem;
  /* 만다린 리포트 hub (2026-10-31): a latest cover's least width (a row of them on a desk, one in view on a phone) and its
     picture's height, a report card's least width (three or more a row on a desk), the picture beside a report */
  --report-hub-cover: 13.5rem;
  --report-hub-cover-phone: 78%;
  --report-hub-cover-art: 8.5rem;
  --report-hub-card: 19rem;
  --report-hub-thumb: var(--space-16);
  --opacity-ray: .82;
  --opacity-dot: .38;
  --prism-lock-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 10V7a5 5 0 0 1 10 0v3h1a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1zm2 0h6V7a3 3 0 0 0-6 0z'/%3E%3C/svg%3E");
  /* 만다린 프리즘: the direction mark of a chain or a money flow (a mask; the colour is the element's). */
  --prism-arrow-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 11h12.2l-4.6-4.6L13 5l7 7-7 7-1.4-1.4 4.6-4.6H4z'/%3E%3C/svg%3E");
  --icon-deep-edition: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M8 3h11a2 2 0 0 1 2 2v11h-2V5H8zM3 8a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zm2 0v11h10V8zm2 3h6v2H7zm0 4h4v2H7z'/%3E%3C/svg%3E");
  --icon-dispatch: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 11.5 21 4l-3.2 16-5.3-4.2-3 2.9v-4.8L16.5 8l-8.9 5.6z'/%3E%3C/svg%3E");
  --deep-band-bg: linear-gradient(135deg, color-mix(in srgb, var(--brand) 16%, var(--surface)), var(--surface) 70%);
  --deep-band-sheen: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--brand) 24%, transparent) 50%, transparent 70%);
  --deep-band-glow: 0 0 var(--space-6) color-mix(in srgb, var(--brand) 18%, transparent);
  --motion-deep-sheen: 1400ms;
  /* 1:1 문의 and FAQ (#ask, #help): the room's width and photo size, its warm tones, and the icons (masks; the colour is the element's). */
  --size-ask-room: 640px;
  --size-ask-photo: 240px;
  --size-help-step: calc(var(--size-icon) + var(--space-2)); /* an FAQ answer's step number disc; the joining line starts under it */
  --ask-room-bg: color-mix(in srgb, var(--brand) 7%, var(--surface));
  --ask-bubble-staff: color-mix(in srgb, var(--text) 9%, var(--ask-room-bg));
  --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M15.5 14h-.8l-.3-.3A6.5 6.5 0 1 0 14 15.5l.3.3v.8l5 5 1.5-1.5-5-5zm-6 0a4.5 4.5 0 1 1 0-9 4.5 4.5 0 0 1 0 9z'/%3E%3C/svg%3E");
  --icon-clear: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 6.4 17.6 5 12 10.6 6.4 5 5 6.4l5.6 5.6L5 17.6 6.4 19l5.6-5.6 5.6 5.6 1.4-1.4-5.6-5.6z'/%3E%3C/svg%3E");
  --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.4 8.6 12 13.2l4.6-4.6L18 10l-6 6-6-6z'/%3E%3C/svg%3E");
  --icon-plus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z'/%3E%3C/svg%3E");
  --icon-send: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m12 4 7 7-1.4 1.4L13 7.8V20h-2V7.8l-4.6 4.6L5 11z'/%3E%3C/svg%3E");
  --icon-thumb-up: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M1 21h4V9H1zm22-11a2 2 0 0 0-2-2h-6.3l.9-4.6v-.3c0-.4-.2-.8-.4-1.1L14.2 1 7.6 7.6C7.2 8 7 8.500 7 9v10a2 2 0 0 0 2 2h9c.8 0 1.5-.5 1.8-1.200l3-7.100c.1-.2.2-.5.2-.7z'/%3E%3C/svg%3E");
  --icon-thumb-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg transform='rotate(180 12 12)'%3E%3Cpath d='M1 21h4V9H1zm22-11a2 2 0 0 0-2-2h-6.3l.9-4.6v-.3c0-.4-.2-.8-.4-1.1L14.2 1 7.6 7.6C7.2 8 7 8.500 7 9v10a2 2 0 0 0 2 2h9c.8 0 1.5-.5 1.8-1.200l3-7.100c.1-.2.2-.5.2-.7z'/%3E%3C/g%3E%3C/svg%3E");
  --icon-topic-account: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zm0 2c-2.700 0-8 1.300-8 4v2h16v-2c0-2.700-5.300-4-8-4z'/%3E%3C/svg%3E");
  --icon-topic-billing: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H4v-6h16zm0-10H4V6h16z'/%3E%3C/svg%3E");
  --icon-topic-reading: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2zM6 4h5v8l-2.500-1.500L6 12z'/%3E%3C/svg%3E");
  --icon-topic-community: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z'/%3E%3C/svg%3E");
  --icon-topic-using: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m12 2 2.900 6.300 6.900.7-5.200 4.600 1.500 6.800L12 16.900 5.900 20.400l1.500-6.800L2.200 9l6.900-.7z'/%3E%3C/svg%3E");
  /* Preview and my page */
  --size-mypage-sally: 190px;
  --size-mypage-sally-compact: 100px;
  --size-mypage-sally-height-narrow: 180px;
  /* Member center (also served to Wagle as mockup/styles/member-center.css) */
  --member-center-width: 90rem;
  --member-center-nav: 11rem;
  --member-center-nav-compact: 9rem;
  --member-center-content-min: 16rem;
  --member-center-editor-min: 20rem;
  --member-center-editor-max: 26rem;
  --member-center-icon: 1.125rem;
  --member-center-preferences: 42rem;
  --member-center-content-max: 56rem;
  --member-card-min: 15rem;
  --member-center-textarea: 6rem;
  --member-center-drawer: 40rem;
  --member-center-drawer-compact: 34rem;
  --member-center-drawer-clearance: 10rem;
  --member-center-drawer-clearance-compact: 8rem;
  --member-center-drawer-textarea-min: 7rem;
  --member-center-drawer-textarea-max: 14rem;
  /* 만다린 토스트 (morning edition): the page's reading width, the banner picture, a thermometer bar, the drawn
     thermometers at their widest (a phone's width: wider and the tubes outgrow the words), the unread dot */
  --size-toast-reading: 52rem;
  --size-toast-art: 22rem;
  --size-toast-bar: 0.375rem;
  --size-toast-thermo: 26rem;
  --size-toast-dot: 0.5rem;
  /* 특별한 날 (special-days.cjs): the day's picture beside its one line on the home and Wagle */
  --size-special-day-band: clamp(9rem, 26vw, 15rem); /* the special day's picture as a band across the page (2026-11-11: a small picture left half the card empty) */
  --special-day-focus: 55%; /* where the band crops the day's picture from the top; a day whose heads were cut sets its own on the figure */
  /* Staff workbench (admin) */
  --size-ops-search: 180px;
  --size-ops-detail-min: 280px;
  --size-ops-detail: 340px;
  --size-ops-label: 150px;
  --size-ops-filter: 120px;
  --size-ops-table-min: 460px;
  /* Print */
  --print-rule-width: .25mm;
  --print-label-width: 23mm;
}

/* 2. Semantic roles — dark (default) */
:root {
  color-scheme: dark;
  --canvas: var(--neutral-950);
  --surface: var(--neutral-900);
  --surface-raised: var(--neutral-850);
  --surface-hover: var(--neutral-800);
  --border: var(--neutral-750);
  --border-control: var(--neutral-500);
  --text: var(--neutral-50);
  --text-secondary: var(--neutral-300);
  --text-muted: var(--neutral-350);
  --brand: var(--orange-400);
  --brand-hover: var(--orange-300);
  --on-brand: var(--orange-950);
  --brand-button-fill: var(--orange-400);
  --brand-button-hover-fill: var(--orange-300);
  --on-brand-button: var(--orange-950);
  --fact: var(--orange-300);
  --comparison: var(--violet-300);
  --condition: var(--teal-300);
  --up: var(--red-300);
  --down: var(--blue-300);
  --unknown: var(--gray-300);
  --friend-surface: var(--forest-900);
  --friend-border: var(--forest-700);
  /* Section families (2026-11-01, home headings B): one accent per family of sections. Context is the colour the graph's
     context hulls and the context controls already use (the brand), so a 만다린 맥락 reads in one colour on the graph,
     the home rails and the reports. --on-family is the ink of an icon on an accent plate. */
  --family-market: var(--violet-300);
  --family-context: var(--brand);
  --family-companies: var(--teal-300);
  --family-journal: var(--pink-300);
  --on-family: var(--neutral-950);
  --attribution-surface: var(--neutral-0);

  --media-canvas: var(--neutral-975);
  --media-text: var(--neutral-0);
  --media-secondary: var(--neutral-200);
  --media-brand: var(--orange-400);
  --media-fact: var(--orange-300);
  --media-comparison: var(--violet-300);
  --media-condition: var(--teal-300);
  --media-japan: var(--yellow-300);
  --media-china: var(--pink-300);
  --media-germany: var(--sky-300);
  --media-uk: var(--green-300);
  --media-dow: var(--lime-300);
  --media-nasdaq: var(--cyan-300);
  --media-sox: var(--fuchsia-300);
  --media-node: color-mix(in srgb, var(--neutral-925) 91%, transparent);
  --media-edge: color-mix(in srgb, var(--slate-300) 50%, transparent);
  /* One colour per relation kind on the graph's dark canvas (lines, legend, panel). */
  --graph-line-holding: var(--orange-400);
  --graph-line-customer: var(--teal-300);
  --graph-line-supplier: var(--sky-300);
  --graph-line-partner: var(--violet-300);
  --graph-line-contract: var(--yellow-300);
  --graph-line-merger: var(--pink-300);
  --graph-line-other: var(--slate-300);
  --graph-hull-fill: color-mix(in srgb, var(--orange-400) 7%, transparent);
  --graph-hull-stroke: color-mix(in srgb, var(--orange-400) 40%, transparent);
  --media-dot: var(--neutral-250);
  --media-border: color-mix(in srgb, var(--neutral-0) 21%, transparent);
  --media-divider: color-mix(in srgb, var(--neutral-0) 13%, transparent);
  --media-shade: color-mix(in srgb, var(--neutral-975) 50%, transparent);
  --media-muted: var(--neutral-350);
  --media-hit: var(--green-850);     /* a prediction that came true, on a dark picture (share card) */
  --media-miss: var(--red-900);      /* a prediction that missed */

  --overlay-soft: color-mix(in srgb, var(--neutral-1000) 33%, transparent);
  --overlay-medium: color-mix(in srgb, var(--neutral-1000) 53%, transparent);
  --overlay-strong: color-mix(in srgb, var(--neutral-1000) 73%, transparent);
  --overlay-solid: var(--neutral-1000);
  --overlay-header: color-mix(in srgb, var(--neutral-950) 91%, transparent);

  --paper-canvas: var(--cream-50);
  --paper-text: var(--ink-900);
  --paper-muted: var(--ink-700);
  --paper-rule: var(--rule-300);
  --paper-brand: var(--rust-800);
  --print-canvas: var(--neutral-0);
  --print-text: var(--ink-950);
  --print-secondary: var(--ink-600);
  --print-muted: var(--ink-700);
  --print-rule: var(--rule-400);

  --sally-canvas: var(--sage-50);
  --sally-text: var(--sage-800);
  --sally-muted: var(--sage-600);
  --sally-control: var(--sage-150);
  --sally-portrait: var(--sage-400);
  --sally-caption: color-mix(in srgb, var(--sage-75) 91%, transparent);
  --sally-bubble: var(--neutral-0);
  --sally-reply: var(--sage-200);
  --sally-border: var(--sage-300);
  --sally-action: var(--sage-900);
  --sally-on-action: var(--neutral-0);
  --sally-entry: var(--sage-100);
  --sally-entry-shift: var(--space-0);   /* set while the footer shows, so the launcher never covers it (feature-controller.js) */
  --sally-shadow: color-mix(in srgb, var(--sage-850) 3%, transparent);
  --sally-heart: var(--rose-300);
  /* Sally's portrait band in the panel: open (empty room) and folded (talking) heights, where her face sits in the
     picture, the scrim and the ink of her name over it. */
  --sally-portrait-open: clamp(11rem,34vh,17rem);
  --sally-portrait-closed: 5.5rem;
  --sally-portrait-face: 22%;
  /* 2026-11-12, the beret picture as her idle portrait: her face sits lower in it (the beret fills the top), so the open
     band shows the beret down to her chin and the folded band her eyes and smile. */
  --sally-portrait-face-beret: 8%;
  --sally-portrait-face-beret-folded: 36%;
  /* Her other idle pictures (drawn at random at each opening) are half-length with the face a quarter down. */
  --sally-portrait-face-idle: 6%;
  --sally-portrait-face-idle-folded: 26%;
  /* The thinking picture has her face near the top; the folded band at the shared 22% showed her nose and lips only. */
  --sally-portrait-face-thinking-folded: 12%;
  --sally-portrait-scrim: color-mix(in srgb, var(--neutral-975) 62%, transparent);
  --sally-portrait-ink: var(--neutral-0);

  --brand-wash: color-mix(in srgb, var(--brand) 6%, transparent);
  --brand-tint: color-mix(in srgb, var(--brand) 16%, transparent);
  --brand-border: color-mix(in srgb, var(--brand) 40%, transparent);
  --brand-surface: color-mix(in srgb, var(--brand) 5%, var(--surface));
  --fact-wash: color-mix(in srgb, var(--fact) 8%, transparent);
  --fact-border: color-mix(in srgb, var(--fact) 24%, transparent);
  --comparison-wash: color-mix(in srgb, var(--comparison) 8%, transparent);
  --comparison-border: color-mix(in srgb, var(--comparison) 24%, transparent);
  --condition-wash: color-mix(in srgb, var(--condition) 6%, transparent);
  --condition-border: color-mix(in srgb, var(--condition) 25%, transparent);
  /* A section band's soft surface: its family accent mixed into the card surface (text on it is checked in
     validate-design.cjs through the same mix). A rail glyph's square: its kind's colour at --glyph-wash. */
  --family-market-band: color-mix(in srgb, var(--family-market) 8%, var(--surface));
  --family-context-band: color-mix(in srgb, var(--family-context) 8%, var(--surface));
  --family-companies-band: color-mix(in srgb, var(--family-companies) 8%, var(--surface));
  --family-journal-band: color-mix(in srgb, var(--family-journal) 8%, var(--surface));
  --glyph-wash: 16%;

  --shadow-mesh: 0 12px 35px var(--overlay-soft);
  --shadow-sally-bubble: 0 2px 6px var(--sally-shadow);
  --shadow-companion: 0 5px 24px var(--overlay-soft);
  --shadow-rank-text: 0 2px 8px var(--overlay-solid);
  --shadow-current-plan: inset 0 0 0 1px var(--condition);
  --shadow-print: none;
  --shadow-score-text: 0 2px 14px var(--overlay-solid);
  --shadow-flat: none;
  --shadow-dialog: 0 20px 100px var(--overlay-medium);
  --shadow-toast: 0 8px 40px var(--overlay-medium);
}

/* 2. Semantic roles — light */
:root[data-theme="light"] {
  color-scheme: light;
  --canvas: var(--neutral-75);
  --surface: var(--neutral-0);
  --surface-raised: var(--neutral-100);
  --surface-hover: var(--neutral-150);
  --border: var(--neutral-500);
  --border-control: var(--neutral-500);
  --text: var(--neutral-990);
  --text-secondary: var(--neutral-700);
  --text-muted: var(--neutral-600);
  --brand: var(--orange-750);
  --brand-hover: var(--orange-800);
  --on-brand: var(--neutral-0);
  --brand-button-fill: var(--orange-400);
  --brand-button-hover-fill: var(--orange-300);
  --on-brand-button: var(--orange-950);
  --fact: var(--orange-800);
  --comparison: var(--violet-700);
  --condition: var(--teal-800);
  --up: var(--red-700);
  --down: var(--blue-700);
  --unknown: var(--neutral-600);
  --friend-surface: var(--forest-100);
  --friend-border: var(--forest-500);
  --family-market: var(--violet-700);
  --family-context: var(--brand);
  --family-companies: var(--teal-800);
  --family-journal: var(--pink-700);
  --on-family: var(--neutral-0);
}

/* 3. Component roles */
:root {
 /* 만다린 프리즘: one colour per force, kept through the edition (they follow the theme through the roles they name). */
 --prism-market: var(--index-kospi);
 --prism-own: var(--comparison);
 --prism-event: var(--condition);
 --prism-wind: var(--layer-eurusd);
 --prism-link: var(--layer-gold);
 --prism-beam: var(--brand);
 --prism-glass: color-mix(in srgb, var(--brand) 9%, transparent);
 --prism-band: color-mix(in srgb, var(--text) 7%, transparent);
 --prism-band-strong: color-mix(in srgb, var(--text) 26%, transparent);
 --prism-counter-bg: color-mix(in srgb, var(--comparison) 7%, transparent);
 /* 만다린 리포트 (docs/editorial/report-design-system.md §4, 2026-10-30): the cover plate is the same night in both
    themes (a book's cover), so these are not redefined by the light theme; paper turns it to ink on white (print.tokens). */
 --report-plate: var(--neutral-975);
 --report-plate-raised: var(--neutral-925);
 --report-plate-ink: var(--neutral-0);
 --report-plate-muted: var(--neutral-300);
 --report-plate-faint: color-mix(in srgb, var(--neutral-0) 38%, transparent);
 --report-plate-rule: color-mix(in srgb, var(--neutral-0) 14%, transparent);
 --report-plate-scrim: color-mix(in srgb, var(--neutral-975) 72%, transparent);
 /* the light of each edition: its identity, never a force's colour */
 --report-edition-toast: var(--orange-300);
 --report-edition-spotlight: var(--gold-300);
 --report-edition-prism: var(--neutral-0);
 --report-edition-market: var(--ice-300);
 /* the forces drawn on the night plate (fixed: the dark theme's inks) */
 --report-force-market: var(--neutral-0);
 --report-force-own: var(--violet-300);
 --report-force-event: var(--teal-300);
 --report-force-wind: var(--ice-300);
 --report-force-link: var(--gold-300);
 --report-up: var(--red-300);
 --report-down: var(--blue-300);
 /* each analyst's signature: the medal's ring, the lens box's rule, the day's lens corner */
 --analyst-house: var(--orange-400);
 --analyst-value: var(--gold-300);
 --analyst-growth: var(--green-300);
 --analyst-macro: var(--ice-300);
 --analyst-quant: var(--violet-300);
 --analyst-contra: var(--coral-300);
 /* charts: the one thing the figure says, the context around it, the note written on it, the comparison band */
 --report-chart-focus: var(--brand);
 --report-chart-context: color-mix(in srgb, var(--text) 28%, transparent);
 --report-chart-annotation: var(--text);
 --report-chart-band: color-mix(in srgb, var(--text) 8%, transparent);
 --index-kospi: var(--media-text);
 --index-kosdaq: var(--media-comparison);
 --index-sp500: var(--media-condition);
 --index-dow: var(--media-dow);
 --index-nasdaq: var(--media-nasdaq);
 --index-sox: var(--media-sox);
 --index-nikkei225: var(--media-japan);
 --index-shanghai: var(--media-china);
 --index-dax: var(--media-germany);
 --index-uk100: var(--media-uk);
 --layer-usdkrw: var(--red-300);
 --layer-jpykrw: var(--coral-300);
 --layer-eurkrw: var(--indigo-300);
 --layer-cnykrw: var(--rose-300);
 --layer-usdjpy: var(--salmon-300);
 --layer-eurusd: var(--ice-300);
 --layer-usdcny: var(--plum-300);
 --layer-gold: var(--gold-300);
 --layer-silver: var(--gray-300);
 --layer-brent: var(--blue-300);
 --layer-wti: var(--jade-300);
 --layer-copper: var(--bronze-300);
 --layer-nickel: var(--mint-300);
 --layer-aluminium: var(--sand-300);
 --layer-natgas: var(--flame-300);
 --layer-wheat: var(--wheat-300);
 --layer-corn: var(--olive-300);
 --layer-soybean: var(--sage-300);
 --layer-krxgold: var(--ochre-300);
 --layer-gasoline: var(--peach-300);
 --layer-diesel: var(--steel-300);
 --layer-k200fut: var(--aqua-300);
 --layer-vkospi: var(--magenta-300);
 /* Home rails v2 (2026-10-31): a decision filing's kind on the calendar (never red or blue: those are up and down), and
    the warning board's stamps — alarm (a halt, a listing review, delisting …) and caution (designation notices …). */
 --filing-payout: var(--jade-300);
 --filing-contract: var(--gold-300);
 --filing-raise: var(--violet-300);
 --filing-other: var(--steel-300);
 --signal-alarm: var(--coral-300);
 --signal-caution: var(--yellow-300);
 /* A rail title's kind glyph (2026-11-01): the kind's own colour, in both themes through the roles it names. */
 --glyph-up: var(--up);
 --glyph-down: var(--down);
 --glyph-ranking: var(--comparison);
 --glyph-warning: var(--signal-alarm);
 --glyph-filings: var(--filing-contract);
 --glyph-ai: var(--family-journal);
 --glyph-context: var(--family-context);
 --glyph-layer: var(--condition);
 --glyph-followup: var(--fact);
}
:root[data-theme="light"] {
 --index-kospi: var(--slate-800);
 --index-kosdaq: var(--violet-750);
 --index-sp500: var(--teal-700);
 --index-dow: var(--lime-800);
 --index-nasdaq: var(--cyan-700);
 --index-sox: var(--fuchsia-700);
 --index-nikkei225: var(--yellow-800);
 --index-shanghai: var(--pink-700);
 --index-dax: var(--sky-700);
 --index-uk100: var(--green-800);
 --layer-usdkrw: var(--red-700);
 --layer-jpykrw: var(--coral-700);
 --layer-eurkrw: var(--indigo-700);
 --layer-cnykrw: var(--rose-700);
 --layer-usdjpy: var(--salmon-700);
 --layer-eurusd: var(--ice-700);
 --layer-usdcny: var(--plum-700);
 --layer-gold: var(--gold-700);
 --layer-silver: var(--steel-700);
 --layer-brent: var(--blue-700);
 --layer-wti: var(--jade-700);
 --layer-copper: var(--bronze-700);
 --layer-nickel: var(--mint-700);
 --layer-aluminium: var(--sand-700);
 --layer-natgas: var(--flame-700);
 --layer-wheat: var(--wheat-700);
 --layer-corn: var(--olive-700);
 --layer-soybean: var(--sage-800);
 --layer-krxgold: var(--ochre-700);
 --layer-gasoline: var(--peach-700);
 --layer-diesel: var(--steel-700);
 --layer-k200fut: var(--aqua-700);
 --layer-vkospi: var(--magenta-700);
 --filing-payout: var(--jade-700);
 --filing-contract: var(--gold-700);
 --filing-raise: var(--violet-700);
 --filing-other: var(--steel-700);
 --signal-alarm: var(--coral-700);
 --signal-caution: var(--yellow-800);
}

/* 소원나무 is always night (2026-11-01 user: the light theme turned the lower section white): under the light theme the
   #wish page keeps the dark theme's roles, and the roles derived from them on the document are derived again here. */
html[data-theme="light"] .wish-page{color-scheme:dark;--canvas:var(--neutral-950);--surface:var(--neutral-900);--surface-raised:var(--neutral-850);--surface-hover:var(--neutral-800);--border:var(--neutral-750);--border-control:var(--neutral-500);--text:var(--neutral-50);--text-secondary:var(--neutral-300);--text-muted:var(--neutral-350);--brand:var(--orange-400);--brand-hover:var(--orange-300);--on-brand:var(--orange-950);--fact:var(--orange-300);--comparison:var(--violet-300);--condition:var(--teal-300);--up:var(--red-300);--down:var(--blue-300);--unknown:var(--gray-300)}
/* 소원나무의 시간·계절·기념일. The page's own colours are a night's at every hour; the scene's sky follows the clock from the
   hours' roles above (2026-11-14), and the small hours are a deeper night. The season is what drifts in the air (and the snow
   on the ground, at every hour); a day changes the lamps or the moon. */
.wish-page[data-wish-hour="deep"]{--wish-sky:var(--wishsky-990);--wish-level-air:0.85;--wish-level-moon:0.9;--wish-level-star:1.3}
.wish-page[data-wish-season="spring"]{--wish-drift-kind:petal;--wish-drift:var(--wishpetal-100);--wish-level-fly:0.5}
.wish-page[data-wish-season="autumn"]{--wish-drift-kind:leaf;--wish-drift:var(--wishfall-400);--wish-level-fly:0.5}
.wish-page[data-wish-season="winter"]{--wish-drift-kind:snow;--wish-drift:var(--wishsnow-100);--wish-level-fly:0;--wish-ground:var(--wishsnow-700);--wish-dawn-ground:var(--wishsnow-300);--wish-day-ground:var(--wishsnow-300);--wish-dusk-ground:var(--wishsnow-300)}
.wish-page[data-wish-day="witch"]{--wish-lantern:var(--wishwitch-300);--wish-lantern-deep:var(--wishwitch-500);--wish-firefly:var(--wishwitch-300)}
.wish-page[data-wish-day="open"],.wish-page[data-wish-day="santa"]{--wish-lantern:var(--wishopen-300);--wish-lantern-deep:var(--wishopen-500)}
.wish-page[data-wish-day="close"]{--wish-lantern:var(--wishsky-50);--wish-lantern-deep:var(--wishsky-150)}
.wish-page[data-wish-day="newyear"],.wish-page[data-wish-day="seollal"]{--wish-lantern:var(--wishgold-100);--wish-lantern-deep:var(--wishgold-500)}
.wish-page[data-wish-day="daeboreum"],.wish-page[data-wish-day="chuseok"]{--wish-moon-size:1.3;--wish-level-moon:1.3}
.wish-page{--button-bg:var(--surface-raised);--button-fg:var(--text);--button-border:var(--border-control);--button-hover-bg:var(--surface-hover);--button-focus:var(--brand);--utility-fg:var(--text-secondary);--utility-hover-fg:var(--text);--menu-bg:var(--surface);--menu-fg:var(--text);--menu-muted-fg:var(--text-secondary);--menu-border:var(--border);--menu-raised-bg:var(--surface-raised);--menu-accent-fg:var(--brand)}
.market-stage{--button-bg:var(--media-node);--button-fg:var(--media-text);--button-border:var(--media-border);--button-hover-bg:var(--media-divider);--button-focus:var(--media-brand);}
:root{--button-bg:var(--surface-raised);--button-fg:var(--text);--button-border:var(--border-control);--button-hover-bg:var(--surface-hover);--button-primary-bg:var(--brand-button-fill);--button-primary-fg:var(--on-brand-button);--button-primary-hover-bg:var(--brand-button-hover-fill);--button-focus:var(--brand);--utility-fg:var(--text-secondary);--utility-hover-fg:var(--text);--utility-count-bg:var(--brand);--utility-count-fg:var(--on-brand)}
/* 만다린 프리즘 force roles (styles/routes/report.css): a section, a contents entry or a mark names its force, and every
   part inside it reads that force's colour (--force); a figure key names its mark (--mark). */
.prism-report{--force:var(--text-secondary)}
.prism-report [data-force="market"]{--force:var(--prism-market)}
.prism-report [data-force="own"]{--force:var(--prism-own)}
.prism-report [data-force="event"]{--force:var(--prism-event)}
.prism-report [data-force="wind"]{--force:var(--prism-wind)}
.prism-report [data-force="link"]{--force:var(--prism-link)}
/* 만다린 리포트 표지 roles (styles/routes/report-cover.css): the edition's light (--rc-light), a force on the night plate
   (--rc-force: the plate keeps the dark inks in both themes), the analyst's signature (--rc-sign). */
.report-cover,.report-hub-cover,.report-hub-thumb{--rc-light:var(--report-edition-prism)}
.report-cover[data-kind="toast"],.report-hub-cover[data-kind="toast"],.report-hub-thumb[data-kind="toast"]{--rc-light:var(--report-edition-toast)}
.report-cover[data-kind="spotlight"],.report-hub-cover[data-kind="spotlight"],.report-hub-thumb[data-kind="spotlight"]{--rc-light:var(--report-edition-spotlight)}
.report-cover[data-kind="market"],.report-hub-cover[data-kind="market"],.report-hub-thumb[data-kind="market"]{--rc-light:var(--report-edition-market)}
.rc-force{--rc-force:var(--report-force-market)}
.rc-force[data-force="own"]{--rc-force:var(--report-force-own)}
.rc-force[data-force="event"]{--rc-force:var(--report-force-event)}
.rc-force[data-force="wind"]{--rc-force:var(--report-force-wind)}
.rc-force[data-force="link"]{--rc-force:var(--report-force-link)}
.rc-analyst{--rc-sign:var(--analyst-house)}
.prism-theory,.prism-lens{--rc-sign:var(--analyst-house)}
.prism-theory[data-sign="value"],.prism-lens[data-sign="value"]{--rc-sign:var(--analyst-value)}
.prism-theory[data-sign="growth"],.prism-lens[data-sign="growth"]{--rc-sign:var(--analyst-growth)}
.prism-theory[data-sign="macro"],.prism-lens[data-sign="macro"]{--rc-sign:var(--analyst-macro)}
.prism-theory[data-sign="quant"],.prism-lens[data-sign="quant"]{--rc-sign:var(--analyst-quant)}
.prism-theory[data-sign="contra"],.prism-lens[data-sign="contra"]{--rc-sign:var(--analyst-contra)}
/* The signature as letters on the page's own surface (2026-11-13, user: «이론으로 읽으면» in gold-300 on the light raised box was
   unreadable): the signature mixed into the body ink, so it reads in both themes. The plate keeps --rc-sign (its inks stay dark). */
.prism-theory,.prism-lens{--rc-sign-ink:color-mix(in srgb,var(--rc-sign) 35%,var(--text))}
.rc-analyst[data-sign="value"]{--rc-sign:var(--analyst-value)}
.rc-analyst[data-sign="growth"]{--rc-sign:var(--analyst-growth)}
.rc-analyst[data-sign="macro"]{--rc-sign:var(--analyst-macro)}
.rc-analyst[data-sign="quant"]{--rc-sign:var(--analyst-quant)}
.rc-analyst[data-sign="contra"]{--rc-sign:var(--analyst-contra)}
.prism-key-item:is([data-mark="market"]){--mark:var(--prism-market)}
.prism-key-item:is([data-mark="own"]){--mark:var(--prism-own)}
.prism-key-item:is([data-mark="profit"]){--mark:var(--prism-beam)}
.prism-key-item:is([data-mark="revenue"],[data-mark="filed"]){--mark:var(--prism-band-strong)}
.prism-key-item:is([data-mark="fix"]){--mark:var(--prism-event)}
.prism-key-item:is([data-mark="outside"]){--mark:var(--prism-link)}
.prism-key-item:is([data-mark="fit"],[data-mark="last"],[data-mark="value"]){--mark:var(--prism-beam)}
.prism-key-item:is([data-mark="mean"]){--mark:var(--text-secondary)}
.prism-key-item:is([data-mark="all"]){--mark:var(--text-muted)}
.prism-key-item:is([data-mark="peer"]){--mark:var(--text)}
/* Account menu roles (control-contract.css .account-*): the header portrait button and its menu. */
:root{--menu-bg:var(--surface);--menu-fg:var(--text);--menu-muted-fg:var(--text-secondary);--menu-border:var(--border);--menu-raised-bg:var(--surface-raised);--menu-shadow:var(--shadow-toast);--menu-accent-fg:var(--brand);--menu-z:var(--z-popover);--menu-max-height:calc(100dvh - var(--site-chrome-height) - var(--space-4))}
/* Chip colour roles (control-contract.css .chip): neutral, selected (pressed/current), and the up/down/brand tones. */
:root{--chip-fg:var(--text);--chip-muted-fg:var(--text-muted);--chip-bg:transparent;--chip-border:var(--border);--chip-hover-bg:var(--surface-hover);--chip-selected-fg:var(--text);--chip-selected-bg:var(--brand-tint);--chip-selected-border:var(--brand);--chip-up-fg:var(--up);--chip-down-fg:var(--down);--chip-brand-fg:var(--brand);--chip-brand-bg:var(--brand-wash);--chip-brand-border:var(--brand-border);--chip-media-fg:var(--media-text);--chip-media-bg:var(--overlay-strong)}
/* Section headings (control-contract.css .band-heading, .kind-title): the ink, sizes and hover the shared heading asks for. */
:root{--chart-accent:var(--brand);--chart-quiet:var(--text-muted);--chart-band:var(--surface-raised);--chart-band-edge:var(--border-control);--chart-rule:var(--border);--heading-ink:var(--text);--heading-muted:var(--text-muted);--heading-hover:var(--brand);--heading-title-size:var(--text-title-sm);--heading-title-size-compact:var(--text-lg);--heading-rail-size:var(--text-md);--heading-kicker-tracking:var(--tracking-eyebrow)}
:root{--avatar-bg:var(--surface-raised);--avatar-fg:var(--text-secondary)}
/* The market indices strip (control-contract.css .market-ticker): the raised surface with the market up/down colours. */
:root{--ticker-bg:var(--surface);--ticker-border:var(--border);--ticker-fg:var(--text);--ticker-secondary-fg:var(--text-secondary);--ticker-muted-fg:var(--text-muted);--ticker-hover-bg:var(--surface-hover);--ticker-focus:var(--brand);--ticker-pulse:var(--brand);--ticker-pulse-idle:var(--text-muted);--ticker-up-fg:var(--up);--ticker-down-fg:var(--down);--ticker-number-font:var(--font-number)}
/* Site footer roles (control-contract.css .footer): its rule, text, wordmark, accent, face and width. */
:root{--footer-width:var(--content-width);--footer-line:var(--border);--footer-text:var(--text-muted);--footer-strong:var(--text);--footer-accent:var(--brand);--footer-wordmark-font:var(--font-wordmark)}

/* Shared control geometry. Brand colors are supplied by each theme. */
.action-group{display:flex;flex-wrap:wrap;align-items:center;gap:var(--action-group-gap)}
.action-group>.button{display:inline-flex;align-items:center;justify-content:center;text-decoration:none}
:is(button,.button,.file-button){
 box-sizing:border-box;min-height:var(--button-height);min-width:var(--button-min-width);
 padding:var(--button-padding-y) var(--button-padding-x);border-radius:var(--button-radius);
 font-size:var(--button-font-size);font-weight:var(--button-weight);line-height:var(--button-line-height);
 border:var(--stroke-thin) solid var(--button-border);background:var(--button-bg);color:var(--button-fg);
 cursor:pointer;transition:background var(--motion-fast),color var(--motion-fast),border-color var(--motion-fast);
}
:is(button,.button,.file-button):hover{background:var(--button-hover-bg)}
:is(button,.button,.file-button):focus-visible{outline:var(--stroke-focus) solid var(--button-focus);outline-offset:var(--space-1)}
:is(button,.button):disabled{opacity:var(--button-disabled-opacity);cursor:default}
:is(button,.button).primary,.send{background:var(--button-primary-bg);border-color:var(--button-primary-bg);color:var(--button-primary-fg)}
:is(button,.button).primary:hover,.send:hover{background:var(--button-primary-hover-bg)}
@media(prefers-reduced-motion:reduce){:is(button,.button,.file-button){transition:none}}
/* Chips: one pill component for every short label in every service: a company mention, a prediction and its result,
   a choice, a filter, a voice or specialty mark, a status. Something that acts (send, continue, open) is a .button,
   not a chip. The rule, kept by validate-design.cjs serviceChipContract:
   1. Size follows what the chip does, never where it sits. An interactive chip (a, button, summary, label) shows
      --size-chip and its hit area still reaches --size-control-target (WCAG 2.5.5) through an invisible ::after, so a
      compact chip is a full touch target; rows of interactive chips wrap with --chip-row-gap so targets never overlap.
      Any other element is a read-only chip: --size-chip-sm, compact, not a target.
   2. Variants are attributes, never new geometry: selected is aria-pressed="true", aria-current or
      data-state="selected"; data-tone="up|down|brand" colours the label (neutral is the default); <small> inside is
      secondary text. A service may place a chip (margin, alignment, order) but never sizes, pads, rounds or retypes it.
   3. Each theme supplies only the --chip-* colour roles. :where() keeps every rule at one class, so a screen's own
      later rule for .chip still wins the cascade. */
.chip{box-sizing:border-box;display:inline-flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--chip-gap);max-inline-size:100%;min-block-size:var(--size-chip-sm);padding:0 var(--chip-padding-x-sm);border:var(--stroke-thin) solid var(--chip-border);border-radius:var(--chip-radius);background:var(--chip-bg);color:var(--chip-fg);font-size:var(--chip-font-size);font-weight:var(--chip-weight);line-height:var(--leading-ui);text-decoration:none;cursor:default}
.chip:where(a,button,summary,label){position:relative;min-block-size:var(--size-chip);padding-inline:var(--chip-padding-x);cursor:pointer;transition:background var(--motion-fast),color var(--motion-fast),border-color var(--motion-fast)}
.chip:where(a,button,summary,label)::after{content:"";position:absolute;inset-inline:0;inset-block:min(0%,calc((100% - var(--size-control-target))/2))}
.chip:where(a,button,summary,label):hover{background:var(--chip-hover-bg)}
.chip:focus-visible{outline:var(--stroke-focus) solid var(--button-focus);outline-offset:var(--space-1)}
.chip:disabled{opacity:var(--button-disabled-opacity);cursor:default}
.chip:where([aria-pressed="true"],[aria-current]:not([aria-current="false"]),[data-state="selected"]){border-color:var(--chip-selected-border);background:var(--chip-selected-bg);color:var(--chip-selected-fg)}
.chip:where([data-tone="up"]){color:var(--chip-up-fg)}
.chip:where([data-tone="down"]){color:var(--chip-down-fg)}
.chip:where([data-tone="brand"]){border-color:var(--chip-brand-border);background:var(--chip-brand-bg);color:var(--chip-brand-fg)}
/* A chip that sits on a picture (a video's length on its thumbnail): its own dark plate and light letters, readable on any colour
   under it (2026-11-13: the home's 만다린버스TV rail, a white thumbnail under the page's see-through chip). */
.chip:where([data-tone="media"]){border-color:transparent;background:var(--chip-media-bg);color:var(--chip-media-fg)}
.chip small{color:var(--chip-muted-fg)}
.chip[hidden]{display:none}
@media(prefers-reduced-motion:reduce){.chip{transition:none}}
/* Header utilities (language, theme, alerts) in every service: a quiet icon control with no box or fill; the brand
   color marks only an unread count. One definition, so Mandarin, Wagle, Sally and tower headers match; each theme
   supplies only the --utility-* colour roles. */
.utility-switch{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);height:var(--button-target-height);min-height:var(--button-target-height);min-width:var(--button-target-height);padding:0;border:0;border-radius:var(--button-radius);background:transparent;color:var(--utility-fg);font-size:var(--button-font-size-small);font-weight:var(--button-weight);white-space:nowrap}
.utility-switch:hover,.utility-switch:focus-visible{background:transparent;color:var(--utility-hover-fg)}
.utility-switch svg{width:var(--size-header-icon);height:var(--size-header-icon);fill:none;stroke:currentColor;stroke-width:var(--stroke-icon);stroke-linecap:round;stroke-linejoin:round}
.theme-switch{width:var(--button-target-height);padding:0}
.theme-switch .theme-moon,.theme-switch[aria-pressed=true] .theme-sun{display:none}
.theme-switch[aria-pressed=true] .theme-moon{display:block}
.utility-count{position:absolute;inset-block-start:var(--space-1);inset-inline-end:var(--space-1);min-inline-size:var(--space-4);padding:0 var(--space-1);border-radius:var(--radius-pill);background:var(--utility-count-bg);color:var(--utility-count-fg);font-size:var(--text-xs);font-weight:var(--weight-semibold);line-height:var(--leading-solid);padding-block:var(--space-1);text-align:center}
.utility-count:empty{display:none}
/* Header right side, the same in every service and in this order: language, theme, alerts bell, account. A guest
   sees the sign-in button; a member sees the portrait button that opens the account menu (identity, my page,
   service items, sign out, policies). One definition, so Mandarin, Wagle and Sally headers match; each theme supplies
   only the --menu-* roles: colours, the layer (--menu-z) and --menu-max-height (how far below its own header the
   menu may reach). */
.header-utilities{display:flex;align-items:center;gap:var(--space-3)}
.account-controls{position:relative;flex-shrink:0;margin-left:var(--space-3)}
.account-controls [hidden]{display:none!important}
.account-signin{white-space:nowrap}
.account-trigger{display:grid;place-items:center;padding:var(--space-1);width:var(--button-target-height);height:var(--button-target-height);border:var(--stroke-thin) solid transparent;border-radius:var(--radius-control);background:transparent;color:var(--menu-fg)}
.account-trigger:hover,.account-trigger[aria-expanded=true]{background:var(--menu-raised-bg);border-color:var(--menu-border)}
/* The portrait slot holds the shared author avatar (author-avatar.js): sm in the trigger, md in the menu. */
.account-portrait{display:grid;place-items:center;width:100%;height:100%}
.account-popover{position:absolute;right:0;top:calc(100% + var(--space-2));z-index:var(--menu-z);width:min(var(--size-account-popover),calc(100vw - var(--space-8)));padding:var(--space-3);background:var(--menu-bg);color:var(--menu-fg);border:var(--stroke-thin) solid var(--menu-border);border-radius:var(--radius-control);box-shadow:var(--menu-shadow);max-height:var(--menu-max-height);overflow-y:auto;text-align:start}
.account-menu-identity{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-2) var(--space-2) var(--space-4);margin-bottom:var(--space-2)}
.account-menu-identity .account-portrait{width:auto;height:auto;flex-shrink:0}
.account-menu-identity>div{min-width:0}.account-menu-identity strong{display:block;overflow-wrap:anywhere;font-size:var(--text-sm);font-weight:var(--weight-semibold);line-height:var(--leading-ui)}.account-menu-identity p{margin:var(--space-1) 0 0;font-size:var(--text-xs);line-height:var(--leading-body);color:var(--menu-muted-fg)}
.account-popover .account-menu-link,.account-popover .account-menu-signout{display:flex;align-items:center;gap:var(--space-3);width:100%;padding:var(--button-padding-y) var(--button-padding-x);font-size:var(--button-font-size);line-height:var(--button-line-height);font-weight:var(--weight-medium);border-radius:var(--radius-control);color:var(--menu-fg);text-decoration:none;transition:background var(--motion-fast),border-color var(--motion-fast)}
.account-popover .account-menu-link{min-height:var(--button-target-height);background:var(--menu-raised-bg);border:var(--stroke-thin) solid transparent}
.account-popover .account-menu-link+.account-menu-link{margin-top:var(--space-2)}
.account-menu-link svg{flex:none;width:var(--space-5);height:var(--space-5);color:var(--menu-muted-fg);fill:none;stroke:currentColor;stroke-width:var(--stroke-icon);stroke-linecap:round;stroke-linejoin:round}
.account-popover .account-menu-link:hover{background:var(--menu-raised-bg);border-color:var(--menu-border)}
.account-popover .account-menu-signout{justify-content:center;min-height:var(--button-height);margin-top:var(--space-2);background:transparent;border:var(--stroke-thin) solid var(--menu-border);color:var(--menu-muted-fg);font-size:var(--text-xs)}
.account-popover .account-menu-signout:hover{background:var(--menu-raised-bg);color:var(--menu-fg)}
.account-menu-policies{display:flex;justify-content:center;flex-wrap:wrap;gap:var(--space-4);margin-top:var(--space-4);padding-top:var(--space-3);border-top:var(--stroke-thin) solid var(--menu-border);font-size:var(--text-xs);line-height:var(--leading-body);color:var(--menu-muted-fg)}
.account-menu-policies a{color:inherit;text-decoration:none}.account-menu-policies a:hover{color:var(--menu-accent-fg)}
@media(prefers-reduced-motion:reduce){.account-popover :is(.account-menu-link,.account-menu-signout){transition:none}}
/* Icons outside the header: one size and stroke in every service; a context may pick --size-icon-sm. */
.ui-icon{inline-size:var(--size-icon);block-size:var(--size-icon);flex:none;fill:none;stroke:currentColor;stroke-width:var(--stroke-icon);stroke-linecap:round;stroke-linejoin:round}
/* Native select lists (2026-10-11): the open list takes the page theme. A select drawn on a transparent background let
   Windows browsers open a white list with the theme's light text (unreadable in dark mode). */
select{color-scheme:inherit}
select option,select optgroup{background-color:var(--surface);color:var(--text)}
select option:disabled{color:var(--text-secondary)}
/* The one close control (2026-10-10; shared by every service 2026-10-11): an X that turns on hover. Dialogs, drawers and panels use .close-x instead of a
   text button or their own copy of the icon rules. */
.close-x{display:grid;place-items:center;width:var(--button-target-height);min-height:var(--button-target-height);padding:0;background:transparent;border-color:transparent;color:var(--text-secondary)}
dialog .close.close-x{padding:0;min-height:var(--button-target-height)}
.close-x svg{width:var(--size-icon);height:var(--size-icon);transition:transform var(--motion-fast)}
@media(hover:hover){.close-x:hover svg{transform:rotate(90deg)}}
@media(prefers-reduced-motion:reduce){.close-x svg{transition:none}}
/* The world market indices strip above the site header (2026-10-31 user: "상단 주가 나오는 거 나오고 메뉴 두께를 맞춰서
   위로 튀는 듯한 느낌은 없었으면 좋겠어. 지금 샐리를 누르면 위로 올라가는 듯한 느낌이 들어서 리듬을 깨는 것 같다."): one strip
   in Mandarin, Wagle and Sally, --size-market-ticker tall over a --size-site-header header (core tokens), drawn by
   shared/scripts/market-ticker.js. A page holds the empty bar from its first paint, so the quotes arrive without moving
   anything. Geometry here; each theme gives the --ticker-* colours and number face. 600px is --breakpoint-small (this
   file is served unbuilt to Wagle, so the width is written out). */
.market-ticker{box-sizing:border-box;display:flex;align-items:center;gap:var(--space-3);min-width:0;min-block-size:var(--size-market-ticker);padding:var(--space-1) var(--space-6);border-bottom:var(--stroke-thin) solid var(--ticker-border);background:var(--ticker-bg);color:var(--ticker-fg);font-size:var(--text-xs)}
.market-ticker[hidden]{display:none}
.market-ticker-window{flex:1;min-width:0;overflow:hidden}
.market-ticker-track{display:flex;width:max-content;animation:market-roll var(--market-ticker-duration) linear infinite}
.market-ticker-group{display:flex;flex-shrink:0;align-items:center;min-width:100vw;justify-content:space-around}
.market-ticker-item{display:flex;align-items:center;gap:var(--space-3);min-width:var(--market-ticker-item-width);padding-inline:var(--space-6);font-family:var(--ticker-number-font);white-space:nowrap;color:inherit;text-decoration:none;font-variant-numeric:var(--figures-number)}
.market-ticker-item>span{color:var(--ticker-secondary-fg)}
.market-ticker-item small{color:var(--ticker-muted-fg);font-size:var(--text-xs)}
.market-ticker .market-up{color:var(--ticker-up-fg)}
.market-ticker .market-down{color:var(--ticker-down-fg)}
.market-ticker-item:focus-visible{outline:var(--stroke-focus) solid var(--ticker-focus);outline-offset:calc(-1 * var(--space-1))}
.market-ticker-toggle{display:inline-flex;align-items:center;justify-content:center;flex:none;min-width:var(--button-target-height);min-height:var(--button-target-height);border:0;border-radius:var(--button-radius);background:transparent;color:var(--ticker-secondary-fg);cursor:pointer}
.market-ticker-toggle:hover{background:var(--ticker-hover-bg)}
.market-ticker-pulse{position:relative;flex:none;inline-size:var(--market-pulse-size);block-size:var(--market-pulse-size);border-radius:50%;background:var(--ticker-pulse)}
.market-ticker-pulse::after{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--ticker-pulse);animation:market-pulse var(--motion-pulse) ease-out infinite}
.market-ticker-pulse[data-state=stale]{background:var(--ticker-pulse-idle)}
.market-ticker-pulse[data-state=stale]::after{content:none}
@keyframes market-pulse{0%{transform:scale(1);opacity:.75}70%,100%{transform:scale(2.6);opacity:0}}
.market-ticker-toggle svg{width:var(--size-header-icon);height:var(--size-header-icon);pointer-events:none}
.market-ticker[data-paused=true] .market-ticker-track,.market-ticker-window:focus-within .market-ticker-track{animation-play-state:paused}
@media(hover:hover) and (pointer:fine){.market-ticker-window:hover .market-ticker-track{animation-play-state:paused}}
@keyframes market-roll{to{transform:translateX(-50%)}}
@media(prefers-reduced-motion:reduce){.market-ticker-pulse::after{content:none}.market-ticker-track{animation:none}.market-ticker-window{overflow-x:auto}.market-ticker-group[aria-hidden=true]{display:none}.market-ticker-toggle{display:none}}
@media(max-width:600px){.market-ticker{padding-inline:var(--space-3);gap:var(--space-2)}.market-ticker-item{padding-inline:var(--space-4)}}
@media print{.market-ticker{display:none}}
/* The site footer (2026-10-24 user: "푸터가 안 들어가 있는 페이지들이 있어 … 구조는 확실하게 통일하자"): one structure in
   every service — the Mandarin wordmark, the tagline, the policy links (About Mandarin, Terms, Privacy) and an optional
   note. Mandarin's app and static pages take the markup from mockup/index.html (static-header.cjs); Wagle and Sally
   write the same markup with their own copy. Geometry here; each theme gives the --footer-* colours, face and width.
   800px is --breakpoint-medium (this file is served unbuilt to Wagle, so the width is written out). */
.footer{box-sizing:border-box;max-width:var(--footer-width);margin:auto;padding:var(--space-6) var(--space-8);border-top:var(--stroke-thin) solid var(--footer-line);display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3) var(--space-6);font-size:var(--text-xs);color:var(--footer-text)}
.footer p{margin:0;font-size:var(--text-xs)}
.footer a{color:inherit;text-decoration:none}
.footer a:hover{color:var(--footer-accent)}
.footer .footer-wordmark{font-family:var(--footer-wordmark-font);font-size:var(--size-footer-wordmark);font-weight:var(--weight-bold);letter-spacing:var(--tracking-footer-wordmark);white-space:nowrap;color:var(--footer-strong)}
.footer-wordmark span{color:var(--footer-accent)}
.footer-policies{display:flex;flex-wrap:wrap;gap:var(--space-2) var(--space-4);margin:0}
.footer .footer-note{margin-left:auto}
@media(max-width:800px){.footer{padding-inline:var(--space-5)}.footer .footer-note{flex-basis:100%;margin-left:0}}
/* The author avatar (2026-10-24 user: "공용 손을 하나 만들어라. 중구난방 다른 모양을 만들지 마라."): one round face for
   every author in every service — a member, a crew reporter or editor, a company guardian, a service account, Sally.
   shared/scripts/author-avatar.js (MandarinAvatar) writes the markup: <span class="avatar" data-size> with the picture
   from the one avatar map, or the initial (data-monogram) when there is no picture or it fails to load. The size is a
   token step (data-size xs|sm|md|lg|xl = --size-avatar-*), never a screen's own width; a screen may only place an avatar
   (margin, position, order). Pictures drawn on a plain ground (guardians) keep their whole figure (data-fit="contain").
   Each theme gives the --avatar-* colours. */
.avatar{--avatar-size:var(--size-avatar-sm);box-sizing:border-box;display:inline-grid;place-items:center;flex:none;inline-size:var(--avatar-size);block-size:var(--avatar-size);overflow:hidden;border-radius:var(--radius-round);background:var(--avatar-bg);color:var(--avatar-fg);font-size:var(--text-sm);font-weight:var(--weight-semibold);line-height:var(--leading-solid);vertical-align:middle;user-select:none}
.avatar[data-size="xs"]{--avatar-size:var(--size-avatar-xs);font-size:var(--text-xs)}
.avatar[data-size="md"]{--avatar-size:var(--size-avatar-md)}
.avatar[data-size="lg"]{--avatar-size:var(--size-avatar-lg);font-size:var(--text-xl)}
.avatar[data-size="xl"]{--avatar-size:var(--size-avatar-xl);font-size:var(--text-xl)}
.avatar>img{display:block;inline-size:100%;block-size:100%;object-fit:cover}
.avatar[data-fit="contain"]>img{object-fit:contain}
/* The profile-header step keeps a phone row free: xl is lg up to 700px (--breakpoint-compact; this file is served unbuilt). */
@media(max-width:700px){.avatar[data-size="xl"]{--avatar-size:var(--size-avatar-lg)}}
/* Section headings (2026-11-01, user: "B안, 니 추천대로 가자"; page-agnostic so every menu page and service can take it):
   .band-heading opens a section — its family's soft surface (data-family market|context|companies|journal → the theme's
   --family-* and --family-*-band), an accent bar at the start, an icon plate (.band-heading-plate, the family's mono mask
   icon on its accent), the kicker above the title (.band-heading-kicker: the local word spoken, the Latin tag aria-hidden),
   the title (h2), muted subtitle lines (.band-heading-sub, data-strong for the one line that says so-what) and the
   action link at the end. .kind-title opens a rail or a block inside a section: its kind glyph (.kind-glyph, a mask icon
   in a rounded square of the kind's colour, data-heading-icon), the title (h3) with its count (the shared .chip) and the
   basis line under it (.kind-title-basis). Markup from MandarinHeading (scripts/page-shell.js). Shapes: core tokens
   --band-*, --glyph-*; colours: theme roles --family-*, --on-family, --glyph-*, and the --heading-* ink and sizes (each brand's theme supplies them). */
.band-heading{display:flex;flex-wrap:wrap;align-items:center;gap:var(--band-gap);margin:0 0 var(--band-gap-after);padding:var(--band-padding-block) var(--band-padding-inline);background:var(--band-surface);border-inline-start:var(--band-accent-width) solid var(--band-accent);border-radius:var(--band-radius)}
.band-heading[data-family="market"]{--band-accent:var(--family-market);--band-surface:var(--family-market-band)}
.band-heading[data-family="context"]{--band-accent:var(--family-context);--band-surface:var(--family-context-band)}
.band-heading[data-family="companies"]{--band-accent:var(--family-companies);--band-surface:var(--family-companies-band)}
.band-heading[data-family="journal"]{--band-accent:var(--family-journal);--band-surface:var(--family-journal-band)}
/* video (2026-11-13, 만다린버스TV shorts on the home): the journal's colours, its own play mark. */
.band-heading[data-family="video"]{--band-accent:var(--family-journal);--band-surface:var(--family-journal-band)}
.band-heading-plate{flex:none;display:grid;place-items:center;width:var(--band-plate);height:var(--band-plate);border-radius:var(--band-plate-radius);background:var(--band-accent);color:var(--on-family)}
.band-heading-plate::before,.kind-glyph::before{content:"";display:block;background:currentColor;-webkit-mask:var(--heading-icon) center/contain no-repeat;mask:var(--heading-icon) center/contain no-repeat}
.band-heading-plate::before{width:var(--band-plate-icon);height:var(--band-plate-icon)}
.band-heading-copy{flex:1 1 var(--band-copy-min);min-width:0;display:grid;gap:var(--space-1)}
.band-heading-kicker{margin:0;color:var(--band-accent);font-size:var(--text-xs);font-weight:var(--weight-bold);letter-spacing:var(--heading-kicker-tracking);line-height:var(--leading-ui);text-transform:uppercase}
.band-heading :is(h1,h2,h3){margin:0;font-size:var(--heading-title-size);line-height:var(--leading-heading)}
.band-heading-sub{margin:0;color:var(--heading-muted);font-size:var(--text-sm);line-height:var(--leading-ui)}
.band-heading-sub[data-strong]{color:var(--heading-ink);font-weight:var(--weight-semibold)}
.band-heading>.text-link{flex:none;font-size:var(--text-xs)}
.kind-title{display:grid;gap:var(--space-1);min-width:0}
.kind-title :is(h2,h3,h4){display:flex;flex-wrap:wrap;align-items:center;gap:var(--glyph-gap);margin:0;font-size:var(--heading-rail-size);line-height:var(--leading-heading)}
.kind-title :is(h2,h3,h4) a{color:inherit}
.kind-title :is(h2,h3,h4) a:hover,.kind-title :is(h2,h3,h4) a:focus-visible{color:var(--heading-hover)}
.kind-title-basis{margin:0;color:var(--heading-muted);font-size:var(--text-xs);line-height:var(--leading-ui)}
.kind-glyph{flex:none;display:grid;place-items:center;width:var(--glyph-size);height:var(--glyph-size);border-radius:var(--glyph-radius);color:var(--heading-tone);background:color-mix(in srgb,var(--heading-tone) var(--glyph-wash),transparent)}
.kind-glyph::before{width:var(--glyph-icon);height:var(--glyph-icon)}
/* A chart block (2026-11-13, user: "다닥다닥 붙어있고 … 뭘 먼저 먹어야 하는지"): .chart-lead is the block's one bold sentence,
   .chart-legend the keys right above its one chart (.chart-key data-mark: accent = the point, ink = the plain mark, ring = a
   hollow mark, quiet = the neutral grey, band = the usual range), .chart-more folds the rest. Markup from MandarinHeading
   (scripts/page-shell.js). Room between blocks is spacing tokens only. */
.chart-lead{margin:var(--space-2) 0 var(--space-3);color:var(--heading-ink);font-size:var(--text-lg);font-weight:var(--weight-bold);line-height:var(--leading-heading);text-wrap:pretty}
.chart-legend{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1) var(--space-4);margin:0 0 var(--space-2);color:var(--heading-muted);font-size:var(--text-xs);line-height:var(--leading-ui)}
.chart-legend>span{display:inline-flex;align-items:center;gap:var(--space-1)}
.chart-key{flex:none;display:inline-block;width:var(--space-3);height:var(--space-3);border-radius:var(--radius-round);background:var(--heading-ink);border:var(--stroke-emphasis) solid var(--heading-ink)}
.chart-key[data-mark="accent"]{background:var(--chart-accent);border-color:var(--chart-accent)}
.chart-key[data-mark="ring"]{background:transparent;border-color:var(--chart-quiet)}
.chart-key[data-mark="quiet"]{background:var(--chart-quiet);border-color:var(--chart-quiet)}
.chart-key[data-mark="band"]{width:var(--space-4);border-radius:var(--radius-xs);background:var(--chart-band);border-color:var(--chart-band-edge)}
.chart-more{margin-block-start:var(--space-4);border-block-start:var(--stroke-thin) solid var(--chart-rule);padding-block-start:var(--space-3)}
.chart-more>summary{cursor:pointer;color:var(--heading-muted);font-size:var(--text-sm);font-weight:var(--weight-semibold)}
.chart-more>summary:hover,.chart-more>summary:focus-visible{color:var(--heading-hover)}
.chart-more[open]>summary{margin-block-end:var(--space-3)}
/* A phone keeps the band compact, the plate beside the title and the action on its own line (600px = --breakpoint-small; this file is served unbuilt). */
@media(max-width:600px){.band-heading{gap:var(--space-3);padding:var(--space-3) var(--space-4)}.band-heading-copy{flex-basis:0}.band-heading>.text-link{flex-basis:100%}.band-heading :is(h1,h2,h3){font-size:var(--heading-title-size-compact)}}
[data-heading-icon="market"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 17l5.5-5.5 4 4L21 7'/%3E%3Cpath d='M15 7h6v6'/%3E%3C/svg%3E")}
[data-heading-icon="context"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3'/%3E%3C/svg%3E");--heading-tone:var(--glyph-context)}
[data-heading-icon="companies"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 21V4.5A1.5 1.5 0 0 1 5.5 3h9A1.5 1.5 0 0 1 16 4.5V21'/%3E%3Cpath d='M16 9h2.5A1.5 1.5 0 0 1 20 10.5V21'/%3E%3Cpath d='M2.5 21h19'/%3E%3Cpath d='M8 7.5h4M8 11.5h4M8 15.5h4'/%3E%3C/svg%3E")}
[data-heading-icon="journal"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 5H8a4 4 0 0 1 4 4v11a3 3 0 0 0-3-3H2.5z'/%3E%3Cpath d='M21.5 5H16a4 4 0 0 0-4 4v11a3 3 0 0 1 3-3h6.5z'/%3E%3C/svg%3E")}
[data-heading-icon="video"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='3'/%3E%3Cpath d='M10 9.5v5l4.5-2.5z'/%3E%3C/svg%3E")}
[data-heading-icon="up"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M12 4.5l8.5 14h-17z'/%3E%3C/svg%3E");--heading-tone:var(--glyph-up)}
[data-heading-icon="down"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M12 19.5l-8.5-14h17z'/%3E%3C/svg%3E");--heading-tone:var(--glyph-down)}
[data-heading-icon="ranking"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 20V4M3 8l4-4 4 4M17 4v16M13 16l4 4 4-4'/%3E%3C/svg%3E");--heading-tone:var(--glyph-ranking)}
[data-heading-icon="warning"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4v10M12 19.6v.4'/%3E%3C/svg%3E");--heading-tone:var(--glyph-warning)}
[data-heading-icon="filings"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3h8.5L19 7.5V21H6z'/%3E%3Cpath d='M14 3v5h5M9 12.5h7M9 16.5h7'/%3E%3C/svg%3E");--heading-tone:var(--glyph-filings)}
[data-heading-icon="ai"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M12 2c.9 5.4 4.6 9.1 10 10-5.4.9-9.1 4.6-10 10-.9-5.4-4.6-9.1-10-10 5.4-.9 9.1-4.6 10-10z'/%3E%3C/svg%3E");--heading-tone:var(--glyph-ai)}
[data-heading-icon="layer"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12.5c2.5-5.5 5-5.5 7.5 0s5 5.5 7.5 0c1.4-3 3-3.5 5-2'/%3E%3C/svg%3E");--heading-tone:var(--glyph-layer)}
[data-heading-icon="followup"]{--heading-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h15M13.5 6l6 6-6 6'/%3E%3C/svg%3E");--heading-tone:var(--glyph-followup)}
