/* ============================================================================================
   ScaleLounge design system
   ============================================================================================

   One place for the brand. Every surface (public site, client portal, admin, score, emails where
   CSS survives) consumes these tokens instead of carrying its own hex values, which is what the
   codebase did before: scalelounge.html held 140 hard-coded colours, portal.html 209, admin.html
   194, and each page redefined its own :root.

   THE PALETTE IS NOT A GUESS. It was read out of the approved mockup PDF by inflating its content
   streams and totalling the painted area per colour. That is where the extended neutral ramps come
   from, and it is why champagne appears here as a small-area accent: in the approved design it
   covers about 3% of what the ivory does.

   CONTRAST IS MEASURED, NOT ASSUMED. Every pair below that carries text was checked against WCAG.
   Two results shaped the system and must not be undone:

     champagne (#B79A63) on ivory (#F6F3ED) is 2.43:1. It FAILS at every size. Champagne is
     therefore never text on a light surface. On charcoal it is 6.68:1 and fine.

     stone (#D8D3C8) on ivory is 1.35:1, far under the 3:1 a UI component needs. Stone is a
     quiet divider, never a focus ring and never the only signal that something is selected.

   Ratios are recorded next to each token so the next person can see the cost of changing one.
   ============================================================================================ */

/* ---- 1. Brand primitives -------------------------------------------------------------------
   The five approved colours, plus the ramps the mockup actually painted around them. Nothing in
   the application should reference these directly; use the semantic tokens in section 3. */
:root {
  --sl-ivory: #F6F3ED;                 /* Warm Ivory   - the page */
  --sl-charcoal: #15171A;              /* Deep Charcoal - type and dark sections */
  --sl-champagne: #B79A63;             /* Muted Champagne - accent only */
  --sl-forest: #24332B;                /* Deep Forest  - action and confidence */
  --sl-stone: #D8D3C8;                 /* Soft Stone   - borders */

  /* Light surfaces, lightest first. Taken from the mockup's own fills. */
  --sl-ivory-0: #FBFAF7;               /* raised card, near white but still warm */
  --sl-ivory-1: #F8F6F0;
  --sl-ivory-2: #F6F3ED;               /* = Warm Ivory, the page base */
  --sl-ivory-3: #F0ECE3;
  --sl-ivory-4: #EFEAE0;               /* alternating band */
  --sl-ivory-5: #ECE8E0;               /* pressed / hovered light surface */

  /* Stone ramp: dividers and borders, subtle to strong. */
  --sl-stone-1: #E7E2D9;
  --sl-stone-2: #DEDAD1;
  --sl-stone-3: #D8D3C8;               /* = Soft Stone */

  /* Charcoal ramp: dark sections and the surfaces that sit on them. */
  --sl-charcoal-0: #15171A;            /* = Deep Charcoal, the dark page */
  --sl-charcoal-1: #1C1F1E;            /* raised surface on dark */
  --sl-charcoal-2: #1E2221;            /* raised further */
  --sl-charcoal-3: #373B39;            /* borders on dark */

  /* Forest: action. Hover goes lighter so the button lifts rather than sinks into the page. */
  --sl-forest-0: #24332B;
  --sl-forest-hover: #2E4136;
  --sl-forest-active: #1B2721;
  --sl-forest-tint: #E8EDE8;           /* selected row, quiet success surface */

  /* Champagne. `ink` is the only champagne-family colour allowed as text on a light surface
     (4.93:1). The base tone is for rules, marks, borders and dark-background text. */
  --sl-champagne-0: #B79A63;
  --sl-champagne-ink: #7E663A;         /* 4.93:1 on ivory - AA */
  --sl-champagne-soft: rgba(183, 154, 99, .14);
}

/* ---- 2. Type, space, radius, elevation, motion ---------------------------------------------
   Inter for everything, Inter Display for large marketing headlines.

   Both faces come out of ONE file. Inter v4 carries an optical-size axis (opsz 14 to 32), and
   "Inter Display" is simply that axis at its top end: tighter spacing and slightly closed apertures
   for large type. So the second @font-face below re-declares the same woff2 with opsz pinned to 32.
   The browser downloads 352KB once and gets both, which is why there is no separate display file to
   keep in sync.

   Self-hosted deliberately. The site made a documented choice not to pull fonts from a third party,
   and Inter is SIL OFL, redistributed here with its licence in assets/fonts/Inter-LICENSE.txt. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/inter-variable.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter Display';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/inter-variable.woff2') format('woff2');
  font-variation-settings: 'opsz' 32;
}

/* Titles run on DM Sans, because Katie asked for them to match the ScaleLounge wordmark.
   That was settled by measurement rather than taste: the logo's wordmark is 837px wide over a
   101px cap height, a ratio of 8.287. Rendered at the same cap height, DM Sans at 500 comes out at
   8.280, the closest of fourteen candidates. Manrope was next at 8.251. Montserrat and Work Sans
   were the furthest away, at 9.37 and 9.26, which is why the titles never looked related to the
   logo before. Latin subset, 37KB, SIL OFL, licence alongside it in assets/fonts/. */
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/dmsans-variable.woff2') format('woff2');
}

/* ---- The 2026 marketing type pair ------------------------------------------------------------

   MANROPE for display, INSTRUMENT SANS for body and UI. Both self-hosted variable woff2, latin
   subset, SIL OFL, licences alongside them in assets/fonts/.

   WHY THESE TWO. Manrope has a large x-height and open, slightly geometric shapes that hold up at
   600 without turning into a tech logotype, which is what the brief asked for: distinctive and warm
   rather than another Inter site. Instrument Sans underneath it is quieter and a little narrower,
   so long copy sets tighter without ever competing with a heading. Two families doing two jobs, not
   one family pretending to do both by weight.

   ON THE WORDMARK. The display face was previously chosen by measurement: the logo's wordmark is
   837px wide over a 101px cap height, a ratio of 8.287, and DM Sans at 500 came out at 8.280, the
   closest of fourteen candidates. Manrope was SECOND at 8.251. So this swap costs about 0.4% of
   wordmark match, which is a fraction of a pixel at any size a heading is actually set. Worth
   knowing before anyone assumes the old choice was arbitrary. The logo itself is untouched.

   SIZE. 24KB and 29KB against Inter's 352KB and DM Sans's 37KB. The pair is lighter than either
   file it replaces.

   These faces are declared for the whole codebase but only APPLIED under [data-site="marketing"]
   below, so the public site moves and the portal and admin keep the type their users know until
   that is a decision somebody makes deliberately. */
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/assets/fonts/manrope-variable.woff2') format('woff2');
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/instrumentsans-variable.woff2') format('woff2');
}

:root {
  --sl-font: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  /* DM Sans for titles (it matches the wordmark), Inter behind it for anything DM Sans's latin
     subset does not carry, then the system stack. */
  --sl-font-display: 'DM Sans', 'Inter Display', 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  /* Display sizes track the mockup's own ratios. clamp() so a headline never has to be crammed. */
  --sl-t-hero: clamp(2.6rem, 1.4rem + 3.6vw, 4.6rem);
  --sl-t-h1: clamp(2.1rem, 1.3rem + 2.6vw, 3.4rem);
  --sl-t-h2: clamp(1.7rem, 1.2rem + 1.7vw, 2.5rem);
  --sl-t-h3: clamp(1.25rem, 1.05rem + .7vw, 1.6rem);
  --sl-t-lead: clamp(1.02rem, .96rem + .3vw, 1.18rem);
  --sl-t-body: 1.0625rem;   /* 17px. Reading size, not the minimum a browser will render.   */
  --sl-t-sm: 1rem;         /* 16px. Labels, table bodies, small buttons: still full copy.  */
  --sl-t-xs: .875rem;      /* 14px. The floor for anything a person is meant to read.      */
  --sl-t-eyebrow: .8125rem;/* 13px, and only ever set in caps with wide tracking.          */

  /* Named roles. A screen should say what a piece of text IS, not pick a number: that is how
     a codebase ends up with eleven sizes between 11 and 15px and no rule about any of them.
     These follow the client/product scale, so the portals and the admin share one vocabulary. */
  --sl-t-page: clamp(1.75rem, 1.35rem + 1.1vw, 2.25rem);   /* 28 to 36px  PageTitle       */
  --sl-t-page-sub: 1.125rem;                               /* 18px        PageSubtitle    */
  --sl-t-dash: clamp(1.55rem, 1.25rem + .9vw, 2rem);       /* 25 to 32px  DashboardTitle  */
  --sl-t-section: 1.375rem;                                /* 22px        SectionTitle    */
  --sl-t-section-desc: 1.0625rem;                          /* 17px        SectionDesc     */
  --sl-t-card: 1.125rem;                                   /* 18px        CardTitle       */
  --sl-t-card-desc: 1rem;                                  /* 16px        CardDesc        */
  --sl-t-metric: clamp(2rem, 1.55rem + 1.4vw, 2.75rem);    /* 32 to 44px  MetricValue     */
  --sl-t-metric-label: .9375rem;                           /* 15px        MetricLabel     */
  --sl-t-nav: 1rem;                                        /* 16px        Navigation      */
  --sl-t-btn: 1rem;                                        /* 16px        ButtonText      */
  --sl-t-table: .9375rem;                                  /* 15px        Table body      */
  --sl-t-meta: .875rem;                                    /* 14px        Metadata ONLY   */

  /* Medium for display, per the brief: not thin, not overly bold. */
  --sl-w-display: 500;
  --sl-w-body: 400;
  --sl-w-medium: 500;
  --sl-w-semi: 600;

  --sl-lh-display: 1.08;
  --sl-lh-heading: 1.2;
  --sl-lh-body: 1.6;
  --sl-tracking-display: -.022em;
  --sl-tracking-eyebrow: .13em;

  --sl-space-1: 4px;  --sl-space-2: 8px;   --sl-space-3: 12px; --sl-space-4: 16px;
  --sl-space-5: 24px; --sl-space-6: 32px;  --sl-space-7: 48px; --sl-space-8: 64px;
  --sl-space-9: 96px; --sl-space-10: 128px;

  --sl-radius-sm: 6px;
  --sl-radius: 10px;
  --sl-radius-lg: 14px;
  --sl-radius-xl: 20px;
  --sl-radius-pill: 999px;

  /* Minimal shadows on purpose. Premium here comes from spacing, not from depth effects. */
  --sl-shadow-sm: 0 1px 2px rgba(21, 23, 26, .05);
  --sl-shadow: 0 2px 8px rgba(21, 23, 26, .06);
  --sl-shadow-lg: 0 18px 44px -26px rgba(21, 23, 26, .28);

  --sl-ease: cubic-bezier(.22, .9, .3, 1);
  --sl-dur: .2s;
  --sl-dur-slow: .34s;

  --sl-measure: 68ch;                  /* readable line length for body copy */
  --sl-container: 1120px;
}

/* ============================================================================================
   MARKETING TYPE SCALE   [data-site="marketing"]
   ============================================================================================

   The public site only. Every public marketing page carries data-site="marketing" on <html>;
   portal.html, admin.html and agency-hq.html deliberately do not, so this pass cannot move the type
   under a logged-in customer without somebody choosing that separately. Flipping them later is one
   attribute, which is the point of scoping it here instead of forking the stylesheet.

   Sizes are solved against the brief's reading targets rather than against a ratio: hero 58-68px on
   desktop and 38-48 on a phone, section headings 40-48 / 30-38, subheads 22-26 / 19-22, body
   17-18.4, and nothing a visitor is meant to read below 15px. Each clamp() below was fitted to
   those two ends, so the middle of the range takes care of itself.

   WEIGHTS ARE REAL. Manrope carries 400-800 and Instrument Sans 400-700, so 600, 650 and 700 are
   drawn by the font rather than smeared on by the browser. font-synthesis is switched off below to
   guarantee it: a weight asked for outside a family's range has to look wrong here rather than look
   approximately right and ship. */
[data-site="marketing"] {
  --sl-font: 'Instrument Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --sl-font-display: 'Manrope', 'Instrument Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --sl-t-hero: clamp(2.5rem, 1.6rem + 3.4vw, 4.125rem);      /* 40px at 375, 66px at 1440 */
  --sl-t-h1: clamp(2.25rem, 1.72rem + 2vw, 3.25rem);         /* 36 to 52 */
  /* The biggest single change: section headings topped out at 40px, which read as a large
     paragraph rather than as a section opening. */
  --sl-t-h2: clamp(1.95rem, 1.35rem + 1.9vw, 2.75rem);       /* 31 to 44 */
  --sl-t-h3: clamp(1.3rem, 1.1rem + .7vw, 1.65rem);
  /* Was 16.3 to 18.9px, which is body size doing a subhead's job. */
  --sl-t-lead: clamp(1.2rem, 1.05rem + .6vw, 1.5rem);        /* 19 to 24 */
  --sl-t-body: clamp(1.0625rem, 1rem + .2vw, 1.15rem);       /* 17 to 18.4 */
  --sl-t-sm: clamp(1rem, .95rem + .15vw, 1.125rem);          /* 16 to 18 */
  --sl-t-xs: .9375rem;      /* 15px, up from 14 */
  --sl-t-eyebrow: .875rem;  /* 14px, caps and tracked, up from 13 */

  --sl-t-page-sub: clamp(1.125rem, 1.05rem + .3vw, 1.3rem);
  --sl-t-section: clamp(1.375rem, 1.25rem + .4vw, 1.6rem);
  --sl-t-section-desc: clamp(1.0625rem, 1rem + .2vw, 1.15rem);
  --sl-t-card: clamp(1.125rem, 1.05rem + .25vw, 1.25rem);
  --sl-t-card-desc: clamp(1rem, .95rem + .15vw, 1.125rem);
  --sl-t-page: clamp(1.95rem, 1.5rem + 1.4vw, 2.75rem);
  --sl-t-dash: clamp(1.7rem, 1.4rem + 1vw, 2.25rem);
  --sl-t-metric: clamp(2.2rem, 1.7rem + 1.6vw, 3rem);
  --sl-t-metric-label: 1rem;
  --sl-t-nav: 1.0625rem;    /* 17px */
  --sl-t-btn: 1.0625rem;    /* 17px */
  --sl-t-table: 1rem;       /* 16px. A table is copy too. */
  --sl-t-meta: .875rem;     /* 14px, metadata only: never a sentence somebody has to read */

  /* Manrope at 600 is the voice of the page. 650 on the hero alone, where the extra weight reads
     as confidence rather than as shouting, and 700 on a metric, because a number has to land. */
  --sl-w-display: 600;
  --sl-w-hero: 650;
  --sl-w-metric: 700;
  --sl-w-body: 400;
  --sl-w-medium: 500;
  --sl-w-semi: 600;

  /* Manrope's x-height is larger than DM Sans's at the same size and needs the extra room. */
  --sl-lh-display: 1.1;
  --sl-lh-heading: 1.22;
  --sl-lh-body: 1.65;
  /* Manrope sets tighter than DM Sans unaided, so the old -.022em over-closed it. */
  --sl-tracking-display: -.018em;
  --sl-tracking-eyebrow: .12em;

  --sl-measure: 66ch;
}

[data-site="marketing"] body {
  font-synthesis-weight: none;
  font-synthesis-style: none;
  /* Beats the bare `body` selector in the other brand's fonts.css, which several public pages
     still load and which would otherwise win on load order alone. */
  font-family: var(--sl-font);
}
[data-site="marketing"] h1, [data-site="marketing"] h2, [data-site="marketing"] h3,
[data-site="marketing"] h4, [data-site="marketing"] h5, [data-site="marketing"] h6 {
  font-family: var(--sl-font-display);
}

/* The hero and the metric are the two places with their own weight, so they are the two places
   that need a rule. Everything else inherits --sl-w-display through the existing heading styles. */
[data-site="marketing"] .hero h1,
[data-site="marketing"] h1.hero-title { font-weight: var(--sl-w-hero); }
[data-site="marketing"] .cred-stat b,
[data-site="marketing"] .price-big,
[data-site="marketing"] .sl-metric { font-weight: var(--sl-w-metric); }

/* ============================================================================================
   THE MARKETING PALETTE: FOREST + DUSTY TEAL + SAGE   [data-site="marketing"]
   ============================================================================================

   Approved 2026-09-09. Bound to data-site="marketing", which every public page already carries and
   the portal, admin and agency HQ deliberately do not, so this cannot reach a logged-in customer
   without somebody choosing that separately.

   WHAT ACTUALLY MOVES. Forest keeps the CTA and stays the authority colour, which is the point of
   the direction: teal is not a replacement for it, it is the thing that makes the page memorable
   between the dark moments. The accent slot, which champagne holds today at an unreadable 2.53:1,
   goes to teal instead. The page lightens a step, and two sections take a sage band.

   THE ONE RULE. Dusty teal #4C7A78 is 4.54:1 on ivory, so it PASSES as body text there, but it is
   3.81:1 on sage and would fail inside a band. Rather than have a colour that is legal in some
   places and not others, text uses the ink #3F6866 (5.85 on ivory, 4.91 on sage) everywhere, and
   #4C7A78 is kept for fills, rules, icons and borders where contrast rules do not apply. One rule,
   no exceptions to remember.

   Measured on #FAF8F4 unless stated:
     charcoal #15171A ........... 16.93:1   body and headings
     forest #24332B ............. 12.50:1   the CTA fill and dark anchors
     ivory on forest ............ 12.50:1   the CTA label
     teal ink #3F6866 ...........  5.85:1   links, eyebrows, the hero's second line
     teal ink on sage ...........  4.60:1   the same, inside a band (C2 sage, 4.5 floor)
     charcoal on sage ........... 13.30:1   any copy in a band
     dusty teal #4C7A78 .........  4.54:1   passes, but reserved for fills to keep one rule
   Not used as text: champagne at 2.53:1, which is why it keeps its existing ink for type. */
html[data-site="marketing"] {
  --sl-ivory: #FAF8F4;
  --sl-ivory-0: #FFFFFF;
  --sl-ivory-1: #FCFAF7;
  --sl-ivory-2: #FAF8F4;
  --sl-ivory-3: #F1F4F1;
  --sl-ivory-4: #D3E1DA;      /* sage, the band. C2, approved 2026-09-09. */
  --sl-ivory-5: #D3E0DA;

  --sl-stone-1: #E4EAE5;
  --sl-stone-2: #D6DFD9;
  --sl-stone-3: #C4D1CA;

  --sl-teal: #4C7A78;         /* fills, rules, icons, borders */
  --sl-teal-ink: #3F6866;     /* anything anybody has to read */
  --sl-teal-hover: #3F6866;
  --sl-sage: #D3E1DA;

  /* Forest is untouched on purpose: it keeps the button and the dark bands. */
  --sl-forest-tint: #D3E1DA;

  /* The accent slot moves from champagne to teal. The page maps --t2 to --sl-champagne, so this
     is what carries teal into eyebrows and small accents without editing a single page. */
  --sl-champagne: #4C7A78;
  --sl-champagne-0: #4C7A78;
  --sl-champagne-ink: #3F6866;

  --background-primary: #FAF8F4;
  --background-secondary: #D3E1DA;
  --surface-primary: #FFFFFF;
  --surface-sunken: #F1F4F1;
  --border-subtle: #E4EAE5;
  --border-strong: #C4D1CA;
  --text-accent: #4C7A78;                    /* 4.54:1 on ivory. Passes as text HERE. */
  --accent: #4C7A78;
  --accent-soft: #D3E1DA;
  --focus-ring: #3F6866;                     /* 6.57:1, well over the 3:1 a ring needs */

}

/* SAGE, TWICE. The recognition section and the founder section. NOT the closing block: that is
   already a dark charcoal band with white type, and a band behind it would make the closing line
   unreadable. The page keeps one dark anchor and a lot of ivory between the two sage moments. */
html[data-site="marketing"] #problem,
html[data-site="marketing"] main > section:has(.founder) { background: var(--sl-sage); }
/* Inside a sage band the full teal drops to 3.81:1 and stops being legal for text, so the accent
   steps down to the ink there. This is the whole reason the ink exists. */
html[data-site="marketing"] #problem,
html[data-site="marketing"] main > section:has(.founder) { --text-accent: #3F6866; --t2: #3F6866; }

/* Teal earns a few fills, all of them shapes rather than words. */
html[data-site="marketing"] .pkg .tag { background: var(--sl-teal); color: #FFFFFF; border-color: transparent; }
html[data-site="marketing"] .res-card:hover,
html[data-site="marketing"] .cs-card:hover { border-color: var(--sl-teal); }

/* The sticky header wash follows the page. */
html[data-site="marketing"] header { background: rgba(250, 248, 244, .88); }


/* THE ONE LARGE DISPLAY EMPHASIS, and it is aimed at the text utilities rather than at --grad.
   --grad fills shapes as well as clipping text: the featured plan's button is a bare .btn painted
   with it, so tinting the token turned a primary call to action teal. .grad-txt and the home
   page's .l2 are the only two things that clip a gradient to letterforms, so they are the only two
   that get the teal. At 66px it is far past the 3:1 large text needs, and it is 4.54:1 anyway. */
html[data-site="marketing"] .hero h1 .l2,
html[data-site="marketing"] .grad-txt {
  background-image: linear-gradient(100deg, var(--sl-teal), var(--sl-teal));
}

/* ---- 3. Semantic tokens ---------------------------------------------------------------------
   What the application actually uses. Light context is the default because the public site and the
   portal are predominantly ivory. Anything inside .sl-dark flips to the charcoal set. */
:root {
  --background-primary: var(--sl-ivory-2);
  --background-secondary: var(--sl-ivory-4);
  --surface-primary: var(--sl-ivory-0);
  --surface-elevated: #FFFFFF;
  --surface-sunken: var(--sl-ivory-3);
  --surface-dark: var(--sl-charcoal-0);

  --text-primary: var(--sl-charcoal-0);      /* 16.22:1 on ivory - AAA */
  --text-secondary: #5C625E;                 /*  5.64:1 on ivory - AA  */
  --text-tertiary: #6B716D;                  /*  4.51:1 on ivory - AA  */
  --text-on-dark: var(--sl-ivory-2);         /* 16.22:1 on charcoal - AAA */
  --text-on-dark-secondary: #A9AEAB;         /*  7.98:1 on charcoal - AAA */
  --text-on-dark-tertiary: #8C938F;          /*  5.72:1 on charcoal - AA  */
  --text-accent: var(--sl-champagne-ink);    /*  4.93:1 on ivory - AA. NOT --sl-champagne. */

  --border-subtle: var(--sl-stone-1);
  --border-strong: var(--sl-stone-3);
  --border-dark: var(--sl-charcoal-3);

  --action-primary: var(--sl-forest-0);
  --action-primary-hover: var(--sl-forest-hover);
  --action-primary-active: var(--sl-forest-active);
  --action-primary-text: var(--sl-ivory-2);  /* 11.98:1 on forest - AAA */
  --action-secondary: var(--sl-charcoal-0);
  --action-secondary-text: var(--sl-ivory-2);

  --accent: var(--sl-champagne-0);
  --accent-soft: var(--sl-champagne-soft);

  /* Forest, because it is the only brand colour that clears 3:1 against ivory (11.98:1).
     Stone and champagne both fail as a focus indicator. */
  --focus-ring: var(--sl-forest-0);
  --focus-ring-dark: var(--sl-champagne-0);

  /* Semantic status stays a separate system. These are functional, not decorative brand colours,
     and they are tuned for contrast on ivory rather than picked for looks. */
  --status-success: #2F6B4F;
  --status-success-surface: #E8EDE8;
  --status-warning: #8A6318;
  --status-warning-surface: #F6EEDD;
  --status-error: #A33A34;
  --status-error-surface: #F7E9E7;
  --status-info: #2C5468;
  --status-info-surface: #E7EFF3;
}

/* Dark context. Applied to a section, a card or the whole page. */
.sl-dark {
  --background-primary: var(--sl-charcoal-0);
  --background-secondary: var(--sl-charcoal-1);
  --surface-primary: var(--sl-charcoal-1);
  --surface-elevated: var(--sl-charcoal-2);
  --surface-sunken: #101214;
  --text-primary: var(--sl-ivory-2);
  --text-secondary: var(--text-on-dark-secondary);
  --text-tertiary: var(--text-on-dark-tertiary);
  --text-accent: var(--sl-champagne-0);      /* 6.68:1 on charcoal - fine here, unlike on ivory */
  --border-subtle: var(--sl-charcoal-3);
  --border-strong: #4A4F4C;
  --focus-ring: var(--sl-champagne-0);
  background: var(--background-primary);
  color: var(--text-primary);
}

/* ---- 4. Base ---------------------------------------------------------------------------------
   Loading brand.css is what makes a page a ScaleLounge page, so it sets the family on `body`
   itself rather than waiting for a class. That matters because fonts.css still serves Plus Jakarta
   Sans on purpose: index.html is katielendel.com, Katie's personal site, and it shares that file.
   Rebranding fonts.css would have silently changed the personal site too. On any page that loads
   both, brand.css must come AFTER fonts.css so Inter wins. */
body {
  font-family: var(--sl-font);
  font-optical-sizing: auto;
}
h1, h2, h3, h4, h5, h6 {
  font-family: var(--sl-font-display);
  font-weight: var(--sl-w-display);
  letter-spacing: var(--sl-tracking-display);
}

.sl-body,
body.sl-body {
  font-family: var(--sl-font);
  font-weight: var(--sl-w-body);
  font-size: var(--sl-t-body);
  line-height: var(--sl-lh-body);
  color: var(--text-primary);
  background: var(--background-primary);
  font-optical-sizing: auto;           /* let opsz track the size for everything but the display face */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

.sl-display, .sl-h1, .sl-h2, .sl-h3 {
  font-family: var(--sl-font-display);
  font-weight: var(--sl-w-display);
  line-height: var(--sl-lh-heading);
  letter-spacing: var(--sl-tracking-display);
  color: var(--text-primary);
  margin: 0;
  text-wrap: balance;
}
.sl-display { font-size: var(--sl-t-hero); line-height: var(--sl-lh-display); }
.sl-h1 { font-size: var(--sl-t-h1); }
.sl-h2 { font-size: var(--sl-t-h2); }
.sl-h3 { font-size: var(--sl-t-h3); font-weight: var(--sl-w-semi); letter-spacing: -.012em; }

.sl-lead { font-size: var(--sl-t-lead); color: var(--text-secondary); max-width: var(--sl-measure); margin: 0; }
.sl-muted { color: var(--text-secondary); }
.sl-dim { color: var(--text-tertiary); }

/* The eyebrow is where champagne earns its keep on dark. On light it uses the ink tone, because
   the base champagne is 2.43:1 there and would be a compliance failure in small caps type. */
.sl-eyebrow {
  font-size: var(--sl-t-eyebrow);
  font-weight: var(--sl-w-semi);
  letter-spacing: var(--sl-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-accent);
  margin: 0 0 var(--sl-space-3);
}

.sl-container { width: 100%; max-width: var(--sl-container); margin-inline: auto; padding-inline: var(--sl-space-5); }
.sl-section { padding-block: clamp(56px, 7vw, 112px); }
.sl-rule { height: 1px; border: 0; background: var(--border-subtle); margin: 0; }
.sl-rule-accent { height: 2px; width: 44px; border: 0; background: var(--accent); margin: 0; }

/* ---- 5. Focus -------------------------------------------------------------------------------
   One visible focus treatment everywhere. :focus-visible so a mouse click does not draw it but a
   keyboard tab always does. */
.sl-body :focus-visible,
.sl-btn:focus-visible,
.sl-input:focus-visible,
.sl-select:focus-visible,
.sl-textarea:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--sl-radius-sm);
}

/* ---- 6. Buttons -----------------------------------------------------------------------------
   One primary action per visual area, in forest. Champagne is deliberately not a button colour:
   it is an accent, and charcoal-on-champagne is only 6.68:1 where forest gives 11.98:1. */
.sl-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sl-space-2);
  font-family: var(--sl-font); font-size: var(--sl-t-btn); font-weight: var(--sl-w-semi);
  line-height: 1; letter-spacing: -.005em;
  padding: 13px 22px; border-radius: var(--sl-radius); border: 1px solid transparent;
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background-color var(--sl-dur) var(--sl-ease), border-color var(--sl-dur) var(--sl-ease), color var(--sl-dur) var(--sl-ease);
}
.sl-btn-primary { background: var(--action-primary); color: var(--action-primary-text); }
.sl-btn-primary:hover { background: var(--action-primary-hover); }
.sl-btn-primary:active { background: var(--action-primary-active); }

.sl-btn-secondary { background: transparent; color: var(--text-primary); border-color: var(--border-strong); }
.sl-btn-secondary:hover { border-color: var(--action-primary); background: var(--sl-ivory-5); }
.sl-dark .sl-btn-secondary { color: var(--text-primary); border-color: var(--border-strong); }
.sl-dark .sl-btn-secondary:hover { background: rgba(246, 243, 237, .08); border-color: var(--accent); }

.sl-btn-solid-dark { background: var(--action-secondary); color: var(--action-secondary-text); }
.sl-btn-solid-dark:hover { background: #22262A; }

.sl-btn-tertiary {
  background: none; border: 0; padding: 4px 2px; color: var(--text-primary);
  text-decoration: underline; text-underline-offset: 4px;
  text-decoration-color: var(--border-strong); text-decoration-thickness: 1px;
}
.sl-btn-tertiary:hover { text-decoration-color: var(--action-primary); }

.sl-btn-sm { padding: 10px 17px; font-size: var(--sl-t-btn); }
.sl-btn-lg { padding: 17px 32px; font-size: 1.125rem; }
.sl-btn[disabled], .sl-btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; pointer-events: none; }
.sl-btn-block { width: 100%; }

/* ---- 7. Cards -------------------------------------------------------------------------------
   Restrained on purpose. The brief is explicit that premium does not mean more boxes, so a card
   is a light surface with a stone hairline and almost no shadow. */
.sl-card {
  background: var(--surface-primary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--sl-radius-lg);
  padding: var(--sl-space-5);
  box-shadow: var(--sl-shadow-sm);
}
.sl-card-flat { box-shadow: none; }
.sl-card-dark { background: var(--sl-charcoal-1); border-color: var(--sl-charcoal-3); color: var(--text-on-dark); }
.sl-card-selected { border-color: var(--action-primary); box-shadow: inset 0 0 0 1px var(--action-primary); }
/* Selection is carried by the border AND the left rule, never by colour alone. */
.sl-card-featured { border-color: var(--border-strong); border-left: 3px solid var(--accent); }

/* ---- 8. Forms -------------------------------------------------------------------------------- */
.sl-field { display: block; margin-bottom: var(--sl-space-4); }
.sl-label { display: block; font-size: var(--sl-t-sm); font-weight: var(--sl-w-medium); color: var(--text-primary); margin-bottom: var(--sl-space-2); }
.sl-hint { display: block; font-size: var(--sl-t-xs); color: var(--text-secondary); margin-top: var(--sl-space-2); }

.sl-input, .sl-textarea, .sl-select {
  width: 100%; font-family: var(--sl-font); font-size: var(--sl-t-body); color: var(--text-primary);
  background: var(--surface-elevated);
  border: 1px solid var(--border-strong); border-radius: var(--sl-radius);
  padding: 12px 14px;
  transition: border-color var(--sl-dur) var(--sl-ease), box-shadow var(--sl-dur) var(--sl-ease);
}
.sl-input::placeholder, .sl-textarea::placeholder { color: var(--text-tertiary); }
.sl-input:hover, .sl-textarea:hover, .sl-select:hover { border-color: var(--text-tertiary); }
.sl-input:focus, .sl-textarea:focus, .sl-select:focus {
  border-color: var(--action-primary); box-shadow: 0 0 0 3px rgba(36, 51, 43, .12); outline: none;
}
.sl-textarea { min-height: 120px; resize: vertical; line-height: var(--sl-lh-body); }
.sl-input[disabled], .sl-textarea[disabled], .sl-select[disabled] { background: var(--sl-ivory-5); color: var(--text-tertiary); cursor: not-allowed; }

/* Validation never relies on colour alone: the message text carries the meaning. */
.sl-input[aria-invalid="true"], .sl-textarea[aria-invalid="true"] { border-color: var(--status-error); }
.sl-error { display: block; font-size: var(--sl-t-xs); color: var(--status-error); margin-top: var(--sl-space-2); font-weight: var(--sl-w-medium); }
.sl-ok { display: block; font-size: var(--sl-t-xs); color: var(--status-success); margin-top: var(--sl-space-2); font-weight: var(--sl-w-medium); }

.sl-check { display: inline-flex; align-items: flex-start; gap: var(--sl-space-3); cursor: pointer; font-size: var(--sl-t-sm); }
.sl-check input { width: 18px; height: 18px; accent-color: var(--action-primary); margin: 1px 0 0; flex: 0 0 auto; }

/* ---- 9. Badges and status -------------------------------------------------------------------- */
.sl-badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--sl-t-xs); font-weight: var(--sl-w-semi); letter-spacing: .02em;
  padding: 4px 10px; border-radius: var(--sl-radius-pill);
  background: var(--sl-ivory-5); color: var(--text-secondary); border: 1px solid var(--border-subtle);
}
.sl-badge-accent { background: var(--accent-soft); color: var(--text-accent); border-color: rgba(183, 154, 99, .34); }
.sl-badge-forest { background: var(--sl-forest-tint); color: var(--sl-forest-0); border-color: rgba(36, 51, 43, .22); }
.sl-badge-success { background: var(--status-success-surface); color: var(--status-success); border-color: rgba(47, 107, 79, .25); }
.sl-badge-warning { background: var(--status-warning-surface); color: var(--status-warning); border-color: rgba(138, 99, 24, .25); }
.sl-badge-error { background: var(--status-error-surface); color: var(--status-error); border-color: rgba(163, 58, 52, .25); }

/* ---- 10. Tables ------------------------------------------------------------------------------ */
.sl-table { width: 100%; border-collapse: collapse; font-size: var(--sl-t-table); }
.sl-table th {
  text-align: left; font-weight: var(--sl-w-semi); font-size: var(--sl-t-xs);
  letter-spacing: .06em; text-transform: uppercase; color: var(--text-tertiary);
  padding: 10px 14px; border-bottom: 1px solid var(--border-strong); white-space: nowrap;
}
.sl-table td { padding: 14px; border-bottom: 1px solid var(--border-subtle); color: var(--text-primary); vertical-align: top; }
.sl-table tbody tr:hover { background: var(--sl-ivory-1); }
.sl-table tbody tr[aria-selected="true"] { background: var(--sl-forest-tint); box-shadow: inset 3px 0 0 var(--action-primary); }
.sl-table-wrap { overflow-x: auto; border: 1px solid var(--border-subtle); border-radius: var(--sl-radius-lg); background: var(--surface-primary); }

/* ---- 11. Modals, drawers, toasts, tooltips --------------------------------------------------- */
.sl-scrim { position: fixed; inset: 0; background: rgba(21, 23, 26, .48); z-index: 200; }
.sl-modal {
  position: fixed; z-index: 201; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(560px, calc(100vw - 32px)); max-height: calc(100vh - 64px); overflow: auto;
  background: var(--surface-elevated); border: 1px solid var(--border-subtle);
  border-radius: var(--sl-radius-xl); box-shadow: var(--sl-shadow-lg); padding: var(--sl-space-6);
}
.sl-drawer {
  position: fixed; z-index: 201; top: 0; right: 0; height: 100vh; width: min(460px, 100vw);
  background: var(--surface-elevated); border-left: 1px solid var(--border-subtle);
  box-shadow: var(--sl-shadow-lg); padding: var(--sl-space-6); overflow: auto;
}
.sl-toast {
  display: flex; align-items: center; gap: var(--sl-space-3);
  background: var(--sl-charcoal-0); color: var(--sl-ivory-2);
  border-radius: var(--sl-radius); padding: 13px 18px; font-size: var(--sl-t-sm);
  box-shadow: var(--sl-shadow-lg);
}
.sl-tooltip {
  background: var(--sl-charcoal-0); color: var(--sl-ivory-2);
  font-size: var(--sl-t-xs); padding: 7px 10px; border-radius: var(--sl-radius-sm);
  box-shadow: var(--sl-shadow); max-width: 260px; line-height: 1.45;
}

/* ---- 12. Loading and empty states ------------------------------------------------------------
   A skeleton, not a spinner with brand colours in it. Sweep is suppressed under reduced motion. */
.sl-skeleton {
  background: linear-gradient(90deg, var(--sl-ivory-3) 25%, var(--sl-ivory-5) 37%, var(--sl-ivory-3) 63%);
  background-size: 400% 100%;
  animation: sl-sweep 1.4s ease-in-out infinite;
  border-radius: var(--sl-radius-sm);
}
@keyframes sl-sweep { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.sl-skeleton-line { height: 12px; margin-bottom: 10px; }
.sl-skeleton-line:last-child { width: 62%; }

.sl-empty { text-align: center; padding: var(--sl-space-8) var(--sl-space-5); max-width: 46ch; margin-inline: auto; }
.sl-empty-mark { color: var(--accent); margin-bottom: var(--sl-space-4); }
.sl-empty h3 { font-family: var(--sl-font-display); font-weight: var(--sl-w-medium); font-size: var(--sl-t-h3); color: var(--text-primary); margin: 0 0 var(--sl-space-2); }
.sl-empty p { color: var(--text-secondary); margin: 0 0 var(--sl-space-5); }

/* ---- 13. Navigation -------------------------------------------------------------------------- */
.sl-nav-link {
  font-size: var(--sl-t-sm); font-weight: var(--sl-w-medium); color: var(--text-secondary);
  text-decoration: none; padding: 8px 2px; transition: color var(--sl-dur) var(--sl-ease);
}
.sl-nav-link:hover { color: var(--text-primary); }
/* Current page is marked by weight and a rule, not by colour alone. */
.sl-nav-link[aria-current] { color: var(--text-primary); font-weight: var(--sl-w-semi); box-shadow: inset 0 -2px 0 var(--accent); }

.sl-side-link {
  display: flex; align-items: center; gap: var(--sl-space-3);
  padding: 10px 14px; border-radius: var(--sl-radius); font-size: var(--sl-t-sm);
  color: var(--text-secondary); text-decoration: none;
  transition: background-color var(--sl-dur) var(--sl-ease), color var(--sl-dur) var(--sl-ease);
}
.sl-side-link:hover { background: var(--sl-ivory-5); color: var(--text-primary); }
.sl-side-link[aria-current] { background: var(--sl-forest-tint); color: var(--sl-forest-0); font-weight: var(--sl-w-semi); box-shadow: inset 3px 0 0 var(--action-primary); }

/* ---- 14. Motion ------------------------------------------------------------------------------
   Calm only: fades and small rises. Nothing pulses, glows or floats. */
.sl-rise { animation: sl-rise var(--sl-dur-slow) var(--sl-ease) both; }
@keyframes sl-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.sl-fade { animation: sl-fade var(--sl-dur-slow) var(--sl-ease) both; }
@keyframes sl-fade { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .sl-rise, .sl-fade, .sl-skeleton { animation: none !important; }
  .sl-skeleton { background: var(--sl-ivory-3); }
  * { transition-duration: .01ms !important; }
}


/* ------------------------------------------------------------ no lone last word
   Katie's standing rule: never a single word by itself on a line, in a title or a subtitle.

   balance evens out the lines of a heading, so the last line is never one orphaned word.
   pretty is the property that specifically prevents a widow in running copy, which is what left
   "department." alone under the hero subtitle. Applied here rather than per page, because the
   rule kept being re-broken one component at a time.

   Both degrade silently: a browser without support wraps exactly as it does today. */
h1, h2, h3, h4, h5, h6,
.hero-eyebrow, .eyebrow, .study h2, .sec-head h2 { text-wrap: balance; }
p, li, dd, dt, blockquote, figcaption, summary, .sub, .stand { text-wrap: pretty; }

/* ---------------------------------------------------------------- text roles
   One vocabulary for every ScaleLounge surface. Public pages are more editorial and set their own
   display sizes; these are the product scale, shared by the client portal and the admin. */
.sl-page-title    { font-family: var(--sl-font-display); font-size: var(--sl-t-page); font-weight: var(--sl-w-display);
                    line-height: 1.12; letter-spacing: -.022em; color: var(--text-primary); margin: 0; }
.sl-page-sub      { font-size: var(--sl-t-page-sub); line-height: 1.5; color: var(--text-secondary);
                    max-width: var(--sl-measure); margin: var(--sl-space-2) 0 0; }
.sl-dash-title    { font-family: var(--sl-font-display); font-size: var(--sl-t-dash); font-weight: var(--sl-w-display);
                    line-height: 1.15; letter-spacing: -.02em; color: var(--text-primary); margin: 0; }
.sl-section-title { font-family: var(--sl-font-display); font-size: var(--sl-t-section); font-weight: var(--sl-w-semi);
                    line-height: 1.25; letter-spacing: -.015em; color: var(--text-primary); margin: 0; }
.sl-section-desc  { font-size: var(--sl-t-section-desc); line-height: 1.55; color: var(--text-secondary);
                    max-width: var(--sl-measure); margin: var(--sl-space-2) 0 0; }
.sl-card-title    { font-size: var(--sl-t-card); font-weight: var(--sl-w-semi); line-height: 1.3;
                    letter-spacing: -.01em; color: var(--text-primary); margin: 0; }
.sl-card-desc     { font-size: var(--sl-t-card-desc); line-height: 1.5; color: var(--text-secondary); margin: 0; }
.sl-body          { font-size: var(--sl-t-body); line-height: var(--sl-lh-body, 1.6); color: var(--text-primary); }
.sl-body-muted    { font-size: var(--sl-t-body); line-height: var(--sl-lh-body, 1.6); color: var(--text-secondary); }
.sl-meta          { font-size: var(--sl-t-meta); line-height: 1.45; color: var(--text-tertiary); }
.sl-metric        { font-family: var(--sl-font-display); font-size: var(--sl-t-metric); font-weight: var(--sl-w-display);
                    line-height: 1; letter-spacing: -.03em; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.sl-metric-label  { font-size: var(--sl-t-metric-label); font-weight: var(--sl-w-medium); line-height: 1.35;
                    color: var(--text-secondary); }

/* Prose should not run the full width of a 27 inch display. */
.sl-measure       { max-width: var(--sl-measure); }
