/* Sen is self-hosted now (W14 D10-14) — see static/vendor/google-fonts/.
   An @import here also blocked rendering on a third-party DNS lookup for
   every page that loads this file, which is all of them. */
@import url("../vendor/google-fonts/fonts.91df00d3030f.css");

/* ---------------------------------------------------------------------------
   Geronimo Engineering brand palette.

   The two base values are sampled straight from the logo: the blue of the "g"
   and the gold of the dot/wordmark. Neither clears WCAG AA for normal-size
   text on white on its own (4.05:1 and 3.02:1), so each has a darkened
   -deep variant for text and solid buttons, and a lightened -light variant
   for dark mode. Use the base colors for graphics, fills and focus rings;
   use -deep for anything that is read as text on a light background.
   --------------------------------------------------------------------------- */
:root {
  --brand-blue:        #2887b1;  /* logo "g" — fills, focus rings, borders   */
  --brand-blue-deep:   #1f6d8f;  /* 5.77:1 on white — links, solid buttons   */
  --brand-blue-deeper: #175571;  /* hover/pressed for solid blue             */
  --brand-blue-light:  #5fb3d9;  /* 7.01:1 on #1f1f1f — dark mode            */
  --brand-gold:        #cb8616;  /* logo dot/wordmark — accents on dark      */
  --brand-gold-deep:   #a86d12;  /* hover/pressed for gold                   */
  /* W14 D10-3. `-deep` is 4.32:1 under white text — close, and still below the
     4.5:1 SC 1.4.3 asks for normal-size text, so gold needed the same second
     step blue already had (`--brand-blue-deeper`). 5.92:1 on white, 5.92:1
     under white. Used wherever gold is a SOLID carrying text: the notification
     badge (assistant.css `.as-rail__badge`, 0.68rem/~11px, the worst single
     element measured in the app at 3.02:1) and `.as-dock__all:hover`.
     The base --brand-gold is untouched and still correct for fills, borders,
     rules and focus rings, where SC 1.4.11 asks 3:1 and it measures 3.02. */
  --brand-gold-deeper: #8a5a0d;  /* 5.92:1 either way — gold carrying text   */
  --brand-gold-light:  #e0a446;  /* 7.51:1 on #1f1f1f — dark mode            */
  --brand-gold-tint:   #fdf3e3;  /* pale gold wash for active nav rows       */

  /* This shell's dark-mode neutrals, named. They existed only as loose hex
     inside the !important Tailwind-override rules further down, which made
     five values nobody could find or keep in step. site.css keeps its own
     palette by design (see the note above tokens.css's :root), so they are
     named here rather than borrowed from the app ramp. */
  --dk-surface:      #262626;   /* card/bg stand-in for bg-white/gray-50/100 */
  --dk-surface-deep: #1f1f1f;   /* the page-level dark ground                */
  --dk-line:         #3a3a3a;   /* hairlines                                 */
  --dk-ink:          #e6edf3;   /* text over the two surfaces above          */
  --dk-border:       #46627f;   /* Tailwind .border repaint                  */
  --dk-field:        #2a2a2a;   /* inputs/selects                            */
  --dk-field-line:   #444444;
  --dk-field-ink:    #e5e5e5;
}

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  overflow-x: hidden;
}

/* Keep browser auto color adjustments aligned with site toggle state. */
html {
  color-scheme: light;
}
html.dark {
  color-scheme: dark;
}

body {
  font-family: 'Sen', sans-serif;
  background: #FAFAFA;
  color: #4b5156;
  font-size: 16px;
  line-height: 1.6;
}

/* Accessibility: allows keyboard users to bypass repeated nav */
.skip-link {
  position: absolute;
  top: -100%;
  left: 0;
  background: var(--brand-blue-deep);
  color: white;
  padding: 12px 20px;
  z-index: 9999;
  font-weight: 700;
  text-decoration: none;
  border-radius: 0 0 var(--r-xs) 0;
}
.skip-link:focus {
  top: 0;
}

/* The floor under keyboard focus on the public shell — same shape as the rule
   in pages/main.css, painted with this shell's own ring colour. `:where()`
   keeps it at zero specificity so every bespoke ring below still wins. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--brand-blue);
  outline-offset: 2px;
}

/* Navbar */
/* z-index 1500, not the 999 this used to be: Leaflet stacks its own furniture
   (controls, the layer/legend panel, tooltips) at z-index up to 1000, and the
   map page's toast sits at 1200 — all of which rendered THROUGH the open
   hamburger dropdown, because the dropdown is a child of this fixed, blurred
   navbar and so is trapped in its stacking context. Anything that must cover
   the nav (the plot modal, at 2000) stays above deliberately. */
.navbar { position: fixed; top: 0; width: 100%; background-color: rgba(0, 0, 0, 0.75); backdrop-filter: blur(10px); z-index: 1500; }
/* Keep nav typography stable even when page-specific frameworks (e.g., Tailwind) load. */
.navbar,
.navbar * { font-family: 'Sen', sans-serif !important; }
.navbar-container { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 2.5rem 0.5rem 0.75rem; flex-wrap: nowrap; }
/* `flex-shrink: 0` is what keeps the mark ON the bar. As a shrinkable flex
   item next to a long link list it was squeezed toward zero on a tablet and
   the logo simply vanished, which is how a visitor loses the way home
   (operator, 2026-08-29). */
.nav-logo { display: flex; align-items: center; gap: 1rem; font-weight: bold; font-size: 1.2rem; color: white; text-decoration: none; flex-shrink: 0; }
.nav-logo:focus-visible { outline: 3px solid var(--brand-gold); outline-offset: 2px; }
.nav-logo img { max-height: 60px; width: auto; object-fit: contain; }
.nav-toggle { display: none; font-size: 1.5rem; background: none; border: none; cursor: pointer; color: white; }
.nav-toggle:focus { outline: 3px solid var(--brand-gold); outline-offset: 2px; }
/* 1rem, not 1.5rem, and 9px of item padding below rather than 12px — the
   same trim static/css/app_nav.css took, for the same reason. A SIGNED-IN
   reader now gets the app's eight sections on this bar too (base.html), so
   the public shell carries eleven items on the docs and analytics pages
   instead of seven. Measured in headless Chromium, the untrimmed bar needed
   more than 1,440px and folded itself into the hamburger on every laptop;
   trimmed it fits a 1,280px screen. Nothing is squeezed — `.nav-links > *`
   still refuses to shrink — there is simply less air. Re-measure before
   adding a twelfth item. */
.nav-links { display: flex; gap: 1rem; list-style: none; margin: 0; padding: 0; flex-wrap: nowrap; }
/* Nav items must OVERFLOW rather than squeeze, and this is load-bearing for
   the hamburger. nav_collapse.js decides by asking whether the container's
   scrollWidth exceeds its clientWidth — but flex items shrink by default, so
   instead of overflowing they compressed and their labels wrapped inside
   themselves ("admin-\nandrew", "Sign\nout"). The bar grew a second ROW and
   scrollWidth never exceeded clientWidth, so the measurement saw no overflow
   and the menu never collapsed. Refusing to shrink or wrap turns that
   invisible height growth back into the width overflow the script is looking
   for (operator, 2026-08-29). */
.nav-links > * { flex: 0 0 auto; }
.nav-links a, .nav-links .cm-nav-button { white-space: nowrap; }
/* `inline-block`, and this is the whole Logout alignment fix (operator,
   2026-09-06: "nav bar looks misaligned when logged in"). The signed-in bar
   ends in a <form><button> (the CSRF-protected sign-out below), and a button
   is inline-block by UA default, so its 8px of vertical padding COUNTS toward
   its height while the same padding on these inline anchors did not. Every
   <li> stretched to the button's 40px, the anchors' text sat at the top of
   theirs and the button's text 8px further down: measured in headless
   Chromium, "Logout" rendered 8px below "admin-andrew" on the desktop row and
   its row stood 16px taller than the rest of the collapsed menu. Giving the
   anchors the button's box model, rather than stripping the button's padding,
   keeps every item's hover, focus ring and tap target the same size. */
.nav-links a { display: inline-block; text-decoration: none; color: white; font-weight: 300; padding: 8px 9px; transition: 0.3s; }
.nav-links a:hover { color: var(--brand-gold-light); text-decoration: underline;}
.nav-links a:focus-visible { outline: 3px solid var(--brand-gold); outline-offset: 2px; }
/* The account controls on the public bar (Wave 24 Q5) — here, not in
   community.css, because a community-only account wears this bar on every
   public page (base.html), not only on the board. And HERE in the file, next
   to the anchor rules rather than 500 lines down where they used to be: the
   collapsed menu's light-mode colour (`.nav-links .cm-nav-button { color:
   #2c3e50 }` in the blocks below) has the same specificity as the `color:
   white` here, so whichever comes LATER wins. With this block after the media
   query, white won, and Logout was white text on the white dropdown — present,
   focusable, invisible (measured 2026-09-06). Source order is the fix; keep
   this block above the collapsed-menu rules. */
.nav-links .cm-nav-form { display: inline; margin: 0; }
/* `color: white`, not `inherit`: the sibling links set their colour explicitly
   (`.nav-links a`), so a button inheriting the bar's own colour came out
   visibly dimmer than everything beside it and read as disabled (2026-08-29).
   A control that ends a session must not look like the greyed-out one. */
.nav-links .cm-nav-button { display: inline-block; background: none; border: none; font: inherit; font-weight: 300; color: white; padding: 8px 9px; cursor: pointer; transition: 0.3s; }
.nav-links .cm-nav-button:hover { color: var(--brand-gold-light); text-decoration: underline; }
.nav-links .cm-nav-button:focus-visible { outline: 3px solid var(--brand-gold); outline-offset: 2px; }
.nav-links .cm-nav-user { font-weight: 600; }
.nav-links .active { border-bottom: 2px solid var(--brand-gold); }

@media (max-width: 768px) {
  .nav-toggle { display: block; }
  .navbar-container { flex-wrap: nowrap; }
  /* `gap: 0`: each row is now 40px tall by itself (24px line + the 16px of
     padding that inline-block makes count), which is what the old 24px row
     plus the 1rem gap added up to — so the menu keeps its height and the
     Logout row, which was the only 40px one, stops standing out. */
  .nav-links { position: absolute; top: 100%; left: 0; width: 100%; flex-direction: column; display: none; gap: 0; background: white; padding: 1rem 2rem; border-top: 1px solid #e0e0e0; list-style: none; }
  .nav-links a, .nav-links .cm-nav-button { color: #2c3e50; }
  .nav-links.show { display: flex; }
  .dark-mode .nav-links {
    background-color: #34495e;
    border-top-color: #2c3e50;
  }
  .dark-mode .nav-links a, .dark-mode .nav-links .cm-nav-button { color: #ffffff; }
}

/* The same collapsed state, driven by a CLASS instead of the viewport width.
   static/js/nav_collapse.js adds `nav-compact` to the bar whenever the links
   genuinely overflow it — a tablet in portrait, a long menu, a large font —
   and removes it when they fit again. The media query above stays as the
   first-paint / no-JS state for phones; every rule here mirrors one above,
   so keep the two blocks in step. */

.navbar.nav-compact .nav-toggle {
  display: block;
}
.navbar.nav-compact .navbar-container {
  flex-wrap: nowrap;
}
.navbar.nav-compact .nav-links {
  position: absolute; top: 100%; left: 0; width: 100%; flex-direction: column; display: none; gap: 0; background: white; padding: 1rem 2rem; border-top: 1px solid #e0e0e0; list-style: none;
}
.navbar.nav-compact .nav-links a,
.navbar.nav-compact .nav-links .cm-nav-button {
  color: #2c3e50;
}
.navbar.nav-compact .nav-links.show {
  display: flex;
}
.dark-mode .navbar.nav-compact .nav-links {
  background-color: #34495e;
  border-top-color: #2c3e50;
}
.dark-mode .navbar.nav-compact .nav-links a,
.dark-mode .navbar.nav-compact .nav-links .cm-nav-button {
  color: #ffffff;
}


/* Welcome Section */
.hero-container {
  /* 100vh on mobile includes the space behind the browser's collapsing URL
     bar, and the hero text is bottom-anchored (align-items: flex-end below) —
     so it sat below the visible fold until you scrolled. 100svh is the
     viewport WITH browser chrome showing; the vh line stays as the fallback
     for engines without svh (2026-08-11). */
  height: 100vh;
  height: 100svh;
  width: 100%;
  margin: 0;
  padding: 0;
  /* Self-hosted, and RELATIVE on purpose (W7-07-F1). This was an absolute URL on
     https://www.ocf.berkeley.edu/~scmg/ — shared student web hosting owned by a
     group the Geronimo org is not, holding the full-viewport hero of the public
     anonymous landing page. Whoever holds that account could deface the page or
     log every visitor's IP/UA/Referer. The byte-identical image has been in this
     repo since 8f0d54a8, so nothing had to be vendored from them.
     A relative url() resolves against the stylesheet's own URL, so it follows
     STATIC_URL wherever it points, and collectstatic's ManifestStaticFilesStorage
     rewrites it to the hashed name — an absolute off-host URL does neither.
     Image replaced 2026-08-11 at the operator's request: converted to JPEG
     (2560px, q82) from the HEIC in github.com/marbalino/public-images and
     vendored here for the same self-hosting reasons. Group sites share this
     hero on purpose (see pages/group_site.css). */
  background-image: url("../images/geronimo-iot-background.b23f8126baea.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  display: flex;
  justify-content: center; 
  align-items: flex-end; 
  color: white; 
}

.hero-text {
  text-align: left;
  padding-bottom: 8vh; 
  text-shadow: 2px 2px 10px rgba(0, 0, 0, 0.7);
  font-family: 'Sen', sans-serif;
}

.hero-text h1 { font-weight: bold; font-size: 8.5rem; margin: 0; line-height: 1; }

@media (max-width: 768px) {
  .hero-text h1 { font-size: 4rem; }
  /* A touch more lift on small screens: even with the svh height above, 8vh
     of clearance is thin once the URL bar re-expands over the page. */
  .hero-text { padding-bottom: 12vh; }
}

/* Layout — the same two measures the app shell uses, from tokens.css. No
   gutter of its own: every block inside .page-content (a docs layout, the
   board's .cm-page, a legal article, the home page's sections) brings its own
   padding, so a cap here is the only thing this rule owes them. */
.page-content {
  max-width: var(--nh-page-measure);
  margin: 0 auto;
  padding: 96px 0 0;
}

/* Notices from the messages framework, on the signed-out shell (2026-09-04).
   base.html renders them for every public page — a redirect that explains
   itself is worthless if the page it lands on cannot draw the explanation, and
   an alert-chart refusal landing on the home page was exactly that. The app
   shell's equivalent lives in pages/main.css; this file is the only stylesheet
   base.html loads, so the rules are restated here rather than borrowed.

   Padded horizontally on purpose: .page-content above deliberately has no
   gutter of its own, and this banner is one of the few blocks placed directly
   inside it. Colours are the shared tint tokens, so .dark-mode flips them. */
.page-content > .messages {
  list-style: none;
  margin: 0 auto 1.5rem;
  padding: 0 1rem;
}
.page-content > .messages li {
  padding: 12px 16px;
  margin-bottom: 0.75rem;
  border-radius: var(--r-sm, 6px);
  background: var(--accent-tint, #e6f0f5);
  color: var(--accent-tint-ink, #175571);
}
.page-content > .messages li.success { background: var(--good-tint); color: var(--good-ink); }
.page-content > .messages li.warning { background: var(--warning-tint); color: var(--warning-ink); }
.page-content > .messages li.error { background: var(--critical-tint); color: var(--critical-ink); }

/* Data-heavy pages (analytics, map) use more of the screen on large monitors
   instead of leaving big empty margins, while staying padded on smaller ones. */
.page-content--wide {
  max-width: var(--nh-page-measure-wide);
}
@media (max-width: 768px) {
  .page-content--wide { max-width: 100%; }
}

@media (max-width: 768px) {
  .page-content {
    padding-top: 86px;
  }
}

/* Dark Mode */
.dark-mode { background-color: #1f1f1f; color: #ffffff; }
.dark-mode .navbar { background-color: rgba(0, 0, 0, 0.85); border-color: #313715; }
.dark-mode .nav-logo, .dark-mode .nav-links a { color: #ffffff; }
.dark-mode .nav-links .active { border-bottom: 2px solid var(--brand-blue-light); }
.dark-mode .nav-links a:hover { color: var(--brand-gold-light); text-decoration: underline;}

/* Dark Mode Toggle — the icon alone.

   It used to be a pill reading "🌙 Dark Mode". The words were doing no work the
   icon was not already doing: a sun/moon pair is one of the few genuinely
   universal control glyphs, and the label was the widest thing in a corner that
   also holds the assistant. So the text is HIDDEN rather than deleted — see
   #mode-label below.

   pages/main.css carries its own copy of these rules for the app shell. The two
   have always been separate declarations of the same component; this keeps them
   in step rather than introducing a third arrangement. */
.dark-mode-toggle {
  position: fixed;
  bottom: 20px;
  right: 20px;
  /* The glyph alone, no disc behind it — see the matching block in
     pages/main.css for why, and for the 48px box that assistant.css's
     --as-toggle has to equal. This shell has no assistant on it; the button
     looks the same on both so the app does not have two theme toggles. */
  width: 48px;
  height: 48px;
  padding: 0;
  border: none;
  background: none;
  color: #4b5156;
  font-size: 38px;
  line-height: 1;
  cursor: pointer;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* The icons are inline SVGs drawn in currentColor, so the button's own color
   above is the single place their paint comes from in either theme. */
/* Hidden from sight, kept for screen readers and for the scripts that set its
   text (main.html, site.js, ceden_export.html). `clip-path`, not
   `display:none`: this span backs up the button's aria-label as its accessible
   name, so it stays in the accessibility tree. */
.dark-mode-toggle #mode-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.dark-mode-toggle:focus { outline: 3px solid var(--brand-blue); outline-offset: 2px; }
/* The glyph is currentColor, so dark mode only has to lift the ink. */
.dark-mode .dark-mode-toggle { background: none; border: none; color: #cfd6dc; }

/* The sun and moon are ONE button showing ONE glyph, and `hidden` on the other
   is what does it — except Tailwind's preflight ships `svg,video{display:block}`,
   an AUTHOR rule, which outranks the browser's built-in `[hidden]{display:none}`.
   Every page that loads Tailwind therefore drew the moon and the sun at once.
   Same trap map.css:336 already documents for .plot-overlay; stated again here
   because the cause is a vendored file nobody reads and the symptom is two
   icons in a 48px box. */
.dark-mode-toggle svg[hidden] { display: none; }


/* Footer */
.site-footer { background: #f7f7f7; padding: 24px 0; margin-top: 24px; text-align: center; border-top: 1px solid #e0e0e0; }
.footer-logos { display: flex; justify-content: center; align-items: center; gap: 32px; margin-bottom: 12px; }
.footer-logos img { max-height: 40px; width: auto; }
.site-footer p { margin: 0; color: #666; font-size: 14px; }

.dark-mode .site-footer { background: #34495e; border-top-color: #2c3e50; }
.dark-mode .site-footer p { color: #ddd; }

/* --- The auth card -------------------------------------------------------
   Sign in, register, the three password-reset steps, two-step verification,
   sign-out and the four register/rate-limit notices: twelve templates sharing
   one card, and the front door of the whole product.

   It is on the app's tokens now (static/css/tokens.css, linked from this
   shell's head). It used to be a white card with a #3f4750 slate banner —
   a cold dark rectangle above a form, from the palette the signed-in app has
   just stopped using, so the first thing anyone saw was the one screen that
   looked like a different product from the one behind it.

   The NAV BAR above this card is deliberately untouched. It is the public
   site's bar and it stays the public site's bar; only the card changed. */
.login-container {
  max-width: 640px;
  margin: 120px auto 40px;
  background-color: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 2px 2px 13px -4px rgba(26, 26, 25, 0.10);
  padding: 20px;
  border-radius: var(--r-md);
}

/* The card's head, wearing the same band the signed-in section landings wear —
   including its graduated edge. A staff gauge is the plate that stands in the
   stream, and the band's bottom rule is drawn as one throughout the app; this
   is where somebody meets it first, which is the argument for it being here
   rather than only past the sign-in.

   Redrawn here rather than shared from pages/main.css because that stylesheet
   belongs to the signed-in shell and this document does not load it. The two
   are kept in step by the tokens, which is where the colours live. */
.header-bar {
  background-color: var(--band);
  padding: 20px;
  color: var(--ink);
  border-radius: var(--r-md) var(--r-md) 0 0;
  margin: -20px -20px 20px -20px;
  text-align: center;
  position: relative;
}
.header-bar::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 9px;
  background-image:
    repeating-linear-gradient(to right, var(--tick-major) 0 1px, transparent 1px 40px),
    repeating-linear-gradient(to right, var(--tick) 0 1px, transparent 1px 8px),
    linear-gradient(to top, var(--band-line) 0 1px, transparent 1px);
  background-size: 100% 9px, 100% 5px, 100% 100%;
  background-position: left bottom, left bottom, left bottom;
  background-repeat: repeat-x, repeat-x, no-repeat;
  pointer-events: none;
}
@media (forced-colors: active) {
  .header-bar::after { display: none; }
  .header-bar { border-bottom: 1px solid; }
}
.header-bar h1 { margin: 0; font-size: 1.5rem; color: var(--ink); }

.card-body label { display: block; margin-bottom: 5px; font-weight: 600; color: var(--ink-2); }
.card-body input {
  width: 100%; padding: 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--field);
  color: var(--ink);
  font: inherit;
  box-sizing: border-box;
}
.card-body input:focus { outline: 3px solid var(--accent-ring); outline-offset: 1px; border-color: var(--accent-ring); }

/* The small print under the form: "Forgot your password?", "Need an account?",
   the guest line. Was a stack of Tailwind `text-gray-500 dark:text-gray-400`
   utilities in each of the twelve templates. */
.card-foot { font-size: 0.875rem; color: var(--ink-3); text-align: center; margin-top: 1rem; }
.card-foot + .card-foot { margin-top: 0.5rem; }
.card-foot a, .card-body a { color: var(--link); }
.card-foot a:hover, .card-body a:hover { text-decoration: underline; }

/* Form errors. Tailwind's `text-red-500` measures 3.76:1 on white — under AA,
   on the one message a reader has to be able to find. --critical-ink is 7.17:1.
   The non-field version is a real box rather than a red line, because "your
   username and password didn't match" is the page's answer, not an aside. */
.field-error { display: block; font-size: 0.875rem; color: var(--critical-ink); margin-top: 4px; }
.form-error {
  font-size: 0.9rem;
  color: var(--critical-ink);
  background: var(--critical-tint);
  border: 1px solid var(--critical);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  margin-bottom: 1rem;
}
.form-error ul, .field-error ul { margin: 0; padding-left: 1.1rem; }

.button {
  background-color: var(--accent); color: var(--accent-ink);
  padding: 12px 20px; border: none; border-radius: var(--r-sm);
  font: inherit; font-weight: 600;
  text-align: center; text-decoration: none;
  cursor: pointer; width: 100%; margin-top: 10px;
}
.button:hover { background-color: var(--accent-hover); color: var(--accent-ink); }
.button:focus-visible { outline: 3px solid var(--accent-ring); outline-offset: 2px; }
/* The four notice pages — signed out, reset sent, reset done, link expired —
   have one action and no form, so their button sizes to its label rather than
   spanning a 640px card. */
.button--inline { display: inline-block; width: auto; padding: 12px 26px; }

/* --- the card's own text ---------------------------------------------------
   Each of these replaced the same Tailwind string repeated across eleven
   templates (`text-3xl font-bold tracking-tight dark:text-gray-100`,
   `text-sm text-gray-500 dark:text-gray-400 mt-1`, and so on). The utilities
   held fixed greys with a hand-written `dark:` twin; these hold one token that
   flips itself, so the auth pages stopped being the corner of the product
   where dark mode was maintained by remembering to. */
.login-container--center { text-align: center; }
/* The heading on a card with no band — the notice pages, which have a title and
   a sentence and nothing to head. */
.card-title { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.01em; color: var(--ink); margin: 0 0 1rem; }
/* The line under a title, inside the band. */
.card-sub { font-size: 0.875rem; color: var(--ink-2); margin: 0.25rem 0 0; }
/* The sentence that explains what the page wants before the form asks for it. */
.card-lede { color: var(--ink-2); margin: 0 0 1rem; }
.card-lede--tight { margin-bottom: 0.5rem; }
.card-lede--loose { margin-bottom: 1.5rem; }

/* A message the server put on the page — "we sent you a link", "that code was
   wrong". The error variant is the same box `.form-error` uses, because they
   are the same thing arriving by two different routes. */
.form-message {
  font-size: 0.9rem; text-align: center; margin-bottom: 0.75rem;
  color: var(--ink-2);
}
.form-message--error { color: var(--critical-ink); }

/* Login password toggle */
.password-field-container { position: relative; display: block; width: 100%; }
/* Room for the button, so a long password never runs underneath it. */
.password-field-container input { padding-right: 46px; }
.password-toggle { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: var(--r-xs); background: none; border: none; cursor: pointer; font-size: 18px; color: var(--ink-3); }
.password-toggle:hover { color: var(--ink-2); background: var(--surface-2); }
.password-toggle:focus-visible { outline: 3px solid var(--accent-ring); outline-offset: 2px; }

/* Generic dark mode helpers for Tailwind-like utility classes on content pages */
.dark-mode .bg-white, .dark-mode .bg-gray-50, .dark-mode .bg-gray-100 {
  background-color: var(--dk-surface) !important;
  border-color: var(--dk-line) !important;
}
.dark-mode .home-unified-dark,
.dark-mode .home-unified-dark.bg-white,
.dark-mode .home-unified-dark .bg-gray-50,
.dark-mode .home-unified-dark .bg-white {
  background-color: var(--dk-surface-deep) !important;
}
.dark-mode .text-gray-800, .dark-mode .text-gray-900, .dark-mode .text-gray-700, .dark-mode .text-gray-600, .dark-mode .text-gray-500 { color: var(--dk-ink) !important; }
.dark-mode .border { border-color: var(--dk-border) !important; }

/* Layout Helpers for the Bento Grid */
.bg-cover {background-size: cover; background-position: center; background-repeat: no-repeat;}

/* Ensure smooth hover transitions for the grid cards */
.transition-transform {transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;}

@media (prefers-reduced-motion: reduce) {
  .transition-transform,
  .transition,
  .time-range,
  .corner-button,
  .button {
    transition: none !important;
    animation: none !important;
  }
}

h2.inline-block {padding-bottom: 4px;}

/* Visually hidden utility class for screen-reader-only text */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* For analytics.html (copied from analytics.css) */
.corner-button {
  right: 20px;
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  text-decoration: none;
  border-radius: var(--r-xs);
  font-family: sans-serif;
  font-weight: bold;
  transition: background-color 0.2s ease;
  z-index: 1000;
}
.corner-button:hover { background-color: #0056b3; }


.dark-mode button.time-range:hover { background-color: #375a9e !important; }
.dark-mode .bg-white { background-color: var(--dk-surface) !important; }
.dark-mode select,
.dark-mode input,
.dark-mode button.time-range {
  background-color: var(--dk-field) !important; border-color: var(--dk-field-line) !important; color: var(--dk-field-ink) !important;
}

/* For login.html */
/* The `.dark-mode .card-body label { color: white !important }` that used to be
   here is gone: the label takes --ink-2, which flips itself, so the override
   had nothing left to correct and the !important was fighting a value that no
   longer exists. */

/* --- Back control on a .header-bar -----------------------------------------
   A quiet ghost button: no fill until hover, one hairline border, the label
   doing the work. Deliberately the same treatment `.back-link` already gets on
   the Advanced Analytics and CEDEN headers, so the app gains no second idea of
   what a back control looks like.

   Retuned from translucent white to the band's own ink. It was written against
   the #3f4750 slate this bar used to be — "one translucent white treatment is
   correct in both [themes]" was true of a bar that was the same dark colour in
   both, and is not true of the tinted band that replaced it, where white on
   kraft is unreadable.

   Worth knowing before reusing it: the seven templates the original note names
   — the alert rule forms — extend base/main.html and never load this
   stylesheet, so these rules have not actually reached them for some time.
   They are kept because the auth card can grow a back control at any point and
   this is what one should look like on it. */
.header-bar .back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 13px;
    border: 1px solid var(--band-line);
    border-radius: var(--r-sm);
    color: var(--ink-2);
    font-size: 0.82rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    text-decoration: none;
    transition: color .15s ease, background-color .15s ease, border-color .15s ease;
}
.header-bar .back-link:hover {
    color: var(--ink);
    background-color: var(--surface-2);
    border-color: var(--line-strong);
}
.header-bar .back-link:focus-visible {
    outline: 2px solid var(--accent-ring);
    outline-offset: 2px;
}

/* .header-bar centres its contents, which is right for the pages whose bar holds
   a page title and wrong for the ones whose bar holds only a back control — a
   button floating in the middle of a banner. This modifier is what those pages
   opt into; the 40-odd templates sharing the base class are untouched. */
.header-bar--nav {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    text-align: left;
}

