/* ==========================================================================
   noedra.css — the Noedra area (dark purple theme layer + area chrome)

   Scope: everything under `.area-noedra` (rendered by
   lib/components/areas/area_shell.dart on /noedra/* pages and Noedra PDPs).
   Outside that root nothing changes: header, footer, cart, checkout, quotes
   and account stay the light shop.

   How the theme works: this file ONLY redefines design tokens (`--cms-*`
   surfaces/text from cms-blocks.css, a few `--color-*` used by shared
   chrome) and adds the area-specific components (sub-nav, hero scene).
   The blocks themselves are theme-agnostic (docs/noedra/PORT-PLAN.md D2).
   Sub-brand accents come from `[data-suite]` (cms-blocks.css) — the four
   suite colours are the one thing kept from the prototype's palette;
   typography is the shop's Siemens Sans (D3), density/radii/buttons the
   shop's grammar.

   House rules (scripts/ui-audit/lint-css.mjs): no px except hairlines, no raw
   vw (use var(--vwx)), no width media queries.
   ========================================================================== */

/* ---- whole-site chrome while inside the area --------------------------
   AreaShell stamps <html data-area="noedra"> (see area_shell.dart). From
   here the ground, the fixed header and the footer take the area's dark
   palette so the theme is the whole page, not a dark island in a light
   shop. Overlays (login/cart drawers, mega menu, search) keep the shop's
   light chrome on purpose — they are shop-global surfaces. */
html[data-area="noedra"] body,
html[data-area="noedra"] .app-shell,
html[data-area="noedra"] .main-content { background: #0a0817; }
html[data-area="noedra"] .site-header,
html[data-area="noedra"] .header-main {
  background: linear-gradient(180deg, rgba(10, 8, 23, 0.9) 0%, rgba(17, 14, 36, 0.82) 100%);
}
html[data-area="noedra"] .site-header.header-scrolled { box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.45); }
html[data-area="noedra"] .site-header.checkout-open { background: #0a0817; }
html[data-area="noedra"] .nav-link,
html[data-area="noedra"] .nav-link:hover,
html[data-area="noedra"] .nav-link.active { color: #f2f0fc; }
html[data-area="noedra"] .nav-link:hover { background: rgba(255, 255, 255, 0.06); }
/* logo: the purple "SIEMENS" word goes white on the dark ground; "energy"
   keeps its petrol — the brand's dark-background lockup. */
html[data-area="noedra"] .logo-container svg path[fill="#641E8C"] { fill: #f2f0fc; }
/* action icons are inline SVGs with a hard-coded #242424 stroke/fill */
html[data-area="noedra"] .header-actions svg [stroke="#242424"] { stroke: #f2f0fc; }
html[data-area="noedra"] .header-actions svg [fill="#242424"] { fill: #f2f0fc; }
html[data-area="noedra"] .header-actions .header-action { color: #f2f0fc; }
html[data-area="noedra"] .site-footer,
html[data-area="noedra"] footer { background: #06040f; }

/* ---- token layer ------------------------------------------------------- */
.area-noedra {
  /* prototype base palette (styles.css: --bg-0…--bg-4, --txt-1…3, --core) */
  --noedra-bg-0: #0a0817;
  --noedra-bg-1: #110e24;
  --noedra-bg-2: #161231;
  --noedra-bg-3: #1c173c;
  --noedra-bg-4: #241e4c;
  --noedra-line: rgba(255, 255, 255, 0.09);
  --noedra-line-strong: rgba(255, 255, 255, 0.16);
  --noedra-txt-1: #f2f0fc;
  --noedra-txt-2: #b4aed4;
  /* Lightened from the prototype's #7f79a6, which was the one palette entry
     that could not meet WCAG AA as body-adjacent text. At #7f79a6 every
     tertiary micro-label failed: 4.19:1 on the bg-3 cards (`.cms-ref-*`,
     `.cms-product-card-type`, 94 instances over all 35 PDPs) and 3.64:1 on the
     configurator's raised option tint (`.ncfg-ometa`). #9691ba clears 4.5 on
     all three surfaces it lands on — 6.1:1 on bg-2, 5.7:1 on bg-3, 4.9:1 on
     the option tint — at the same hue. The token is colour-only (never a
     border or background), so nothing but text weight changes. */
  --noedra-txt-3: #9691ba;

  /* map onto the shared block tokens */
  --cms-surface: var(--noedra-bg-0);
  --cms-surface-alt: var(--noedra-bg-1);
  --cms-surface-raised: var(--noedra-bg-3);
  --cms-line: var(--noedra-line);
  --cms-text: var(--noedra-txt-1);
  --cms-text-2: var(--noedra-txt-2);
  --cms-text-3: var(--noedra-txt-3);
  --cms-accent: var(--suite-core);
  --cms-accent-soft: var(--suite-core-soft);
  --cms-accent-ink: #0f0925;

  /* shared shop chrome that reads --color-* inside the area */
  --color-primary: var(--noedra-txt-1);
  --color-gray-900: var(--noedra-txt-1);
  --color-gray-700: var(--noedra-txt-2);
  --color-gray-600: var(--noedra-txt-2);
  --color-gray-500: var(--noedra-txt-3);
  --color-gray-300: var(--noedra-line-strong);
  --color-gray-200: var(--noedra-line);
  --color-gray-100: var(--noedra-bg-3);
  --color-gray-50: var(--noedra-bg-2);
  /* NOT remapped: --color-white stays white — it is used as light-on-dark
     text (cta-banner heading, media-teaser) and must not become the ground. */
  --shadow-card: 0 1.125rem 3.125rem -1.125rem rgba(0, 0, 0, 0.65);

  background: var(--cms-surface);
  color: var(--cms-text);
  color-scheme: dark;
  /* full-bleed: the shell sits inside main-content; paint edge to edge */
  min-height: 60vh;
}
/* Suite accents inside the dark area: brighter "-2" partner as the ink is
   dark on light accents; keep the same hue variables from cms-blocks.css. */
.area-noedra [data-suite="core"] { --cms-accent-ink: #0f0925; }

/* Buttons: the shop's near-black primary would vanish on the dark ground. */
.area-noedra .btn-primary,
.area-noedra .btn.btn-primary {
  background: var(--cms-accent);
  border-color: var(--cms-accent);
  color: var(--cms-accent-ink);
}
.area-noedra .btn-primary:hover { filter: brightness(1.08); }
.area-noedra .btn-secondary,
.area-noedra .btn.btn-secondary {
  background: transparent;
  border-color: var(--noedra-line-strong);
  color: var(--cms-text);
}
.area-noedra .btn-secondary:hover { border-color: var(--cms-accent); color: var(--cms-text); background: var(--cms-accent-soft); }
.area-noedra a { color: inherit; }
.area-noedra .cms-rich-text a, .area-noedra .cms-step-link { color: var(--cms-accent); }
.area-noedra .cms-badge-tip { background: var(--noedra-bg-4); }
.area-noedra .cms-eyebrow::before { background: var(--cms-accent); }
/* Product grids in the area: `auto-fit` instead of `auto-fill` so a grid with
   fewer cards than tracks STRETCHES them to fill the row rather than leaving
   empty tracks — the suite pages routinely show two or three offerings, and
   auto-fill parked them at the left with most of the row blank. Larger floors
   than the shared defaults, so cards read as substantial at desktop width.
   Grouped grids are excluded: they set their own explicit two-track template
   (auto-fit cannot collapse tracks a spanning group label sits across). */
.area-noedra .cms-product-grid:not(.cms-product-grid--grouped) { grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--cms-card-min)), 1fr)); }
.area-noedra .cms-cols-2.cms-product-grid { --cms-card-min: 26rem; }
.area-noedra .cms-cols-3.cms-product-grid { --cms-card-min: 21rem; }
/* Card grids in the area also use auto-fit, so a block holding a single card
   (the Atlas Testing & Validation family panel) stretches it across the row
   instead of parking a ~334px card in the first of four tracks. The card's own
   container query then lays its copy out beside the heading. */
.area-noedra .cms-card-grid .cms-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--cms-card-min)), 1fr)); }
/* …and the declared column count actually holds. The shared floors are small
   enough that auto-fit resolves MORE tracks than the block asked for — Atlas'
   "Credibility" said 3 columns and rendered 5 at 264px each. Stated as an
   explicit track count rather than by tuning the minmax floor, because the
   floor is in rem and the root font-size is itself a fluid clamp (15.04px at
   desktop, not 16px), so floor arithmetic silently lands a track out.
   A one-card block is excluded so it still stretches via the auto-fit rule
   above — that is what makes the Testing & Validation panel full width. */
@media (min-width: 60rem) {
  .area-noedra .cms-card-grid.cms-cols-2 .cms-grid:not(:has(> :only-child)) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .area-noedra .cms-card-grid.cms-cols-3 .cms-grid:not(:has(> :only-child)) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .area-noedra .cms-card-grid.cms-cols-4 .cms-grid:not(:has(> :only-child)) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
/* Product art in the area is 512px ICONS, not photography (the Atlas testing
   packages and tools all use `atlas_tool-icon_*`). The shared `cards` layout
   hands the media a 4:3 box at the full card width, which blew a 512px icon up
   to 650×488 — past its own resolution, so it renders soft, and it dominated a
   624px-tall card. Give it a fixed square plate instead, matching the 8rem
   thumb the `rows` layout uses, and let the copy have the card back. */
.area-noedra .cms-product-card--cards .cms-product-card-media { width: 9rem; }
.area-noedra .cms-product-card--cards .cms-product-card-media img,
.area-noedra .cms-product-card--cards .cms-product-card-media--empty { aspect-ratio: 1 / 1; }
/* base page blocks that hard-code light surfaces in main.css */
.area-noedra .cms-block--text-section,
.area-noedra .cms-block--image-text,
.area-noedra .cms-block--testimonials { background: transparent; }
.area-noedra .cms-block--cta-banner { background: linear-gradient(135deg, var(--noedra-bg-3) 0%, #2d1b69 100%); }
/* skeletons */
.area-noedra .cms-product-card--skeleton,
.area-noedra .cms-ref-card--skeleton,
.area-noedra .cms-page-skeleton { background: linear-gradient(90deg, var(--noedra-bg-2) 25%, var(--noedra-bg-4) 50%, var(--noedra-bg-2) 75%); background-size: 200% 100%; }

/* ---- PDP inside the area (Noedra products, product_page.dart) -----------
   The PDP chrome hard-codes the light shop (white gallery slots, tab bar,
   #1a1a1a text via --se-* fallbacks). Inside the area we (1) remap the --se-*
   surface/text tokens and (2) repaint the few pieces that carry literal
   colours. Layout, spacing and typography are untouched — a Noedra PDP is
   the shop's PDP on a dark ground, not a different page. */
.area-noedra {
  --se-layer-01: var(--noedra-bg-2);
  --se-layer-02: var(--noedra-bg-2);
  --se-layer-02-stroke: var(--noedra-line);
  --se-layer-03-stroke: var(--noedra-line-strong);
  --se-text-default: var(--noedra-txt-1);
  --se-text-secondary: var(--noedra-txt-2);
  --se-text-tertiary: var(--noedra-txt-3);
  --se-text-muted: var(--noedra-txt-3);
  --se-brand-purple: var(--cms-accent);
  --se-brand-purple-light: var(--cms-accent-soft);
  --se-brand-purple-dark: var(--cms-accent);
  --se-border: var(--noedra-line);
}
.area-noedra .product-page { background: var(--noedra-bg-0); color: var(--noedra-txt-1); }
/* Breathing room under the sub-nav, on every page in the area that opens with a
   breadcrumb (measured: the crumb row started at the nav's exact bottom edge,
   gap 0px, on both the PDP and the catalog).
   The light shop is just as tight against its own fixed header, so this is NOT
   a shared-layout bug — the difference is that the area's sub-nav is a distinct
   bar WITH a border-bottom, so a crumb butting against it reads as cramped
   where the light shop's does not. Hence an area-scoped rule rather than a
   change to main.css. Both surfaces are named explicitly: the PDP's `.breadcrumb`
   and the PLP's `.pdl-breadcrumb-row`. */
.area-noedra .product-page .breadcrumb,
.area-noedra .catalog-page .pdl-breadcrumb-row { padding-top: var(--spacing-5); }
.area-noedra .product-page .breadcrumb a,
.area-noedra .product-page .breadcrumb span { color: var(--noedra-txt-2); }
.area-noedra .product-page .breadcrumb a:hover { color: var(--noedra-txt-1); }
/* gallery — .gallery-thumbnail / .gallery-nav-btn were dead selectors here
   until SHOP-950 reinstated a thumbnail strip under the image + centred
   chevrons over it, under exactly those names. .gallery-peek-slot went with
   the peek. */
.area-noedra .gallery-main-slot,
.area-noedra .gallery-thumbnail { background: var(--noedra-bg-2); }
.area-noedra .gallery-thumbnail { border-color: var(--noedra-line); }
.area-noedra .gallery-thumbnail--active { border-color: var(--cms-accent); }
/* A drop shadow does nothing on a dark background — the tiles read as lifted
   via their border instead, so drop the light theme's shadow rather than
   deepen it. */
.area-noedra .gallery-thumbnail { box-shadow: none; }
/* Chevrons are bare (no fill/border) — only the ink colour needs restating. */
.area-noedra .gallery-nav-btn { color: var(--noedra-txt-3); }
.area-noedra .gallery-nav-btn:hover { color: var(--noedra-txt-1); }
/* info rail: title, tabs, accordions, RFQ affordance */
.area-noedra .product-info-container,
.area-noedra .pdp-tab-bar,
.area-noedra .pdp-tab-content { background: var(--noedra-bg-0); }
.area-noedra .pdp-product-title,
.area-noedra .product-info-container h1,
.area-noedra .pdp-accordion-title,
.area-noedra .pdp-info-description,
.area-noedra .product-title { color: var(--noedra-txt-1); }
.area-noedra .pdp-tab { color: var(--noedra-txt-3); border-bottom-color: var(--noedra-line-strong); }
.area-noedra .pdp-tab.active { color: var(--noedra-txt-1); border-color: var(--noedra-txt-1); }
.area-noedra .pdp-tab:hover:not(.active) { color: var(--noedra-txt-2); border-color: var(--noedra-txt-2); }
.area-noedra .pdp-accordion-header { border-color: var(--noedra-line); }
.area-noedra .pdp-accordion-chevron { color: var(--noedra-txt-2); }
.area-noedra .pdp-info-rfq-affordance { background: var(--noedra-bg-2); border-left-color: var(--cms-accent); }
.area-noedra .pdp-info-rfq-affordance-arrow { color: var(--noedra-txt-1); }
/* Info-rail copy that main.css paints with a literal light-theme grey. These
   are shop-wide rules, so they are repainted HERE rather than tokenised in
   main.css — tokenising would shift the light shop's PDPs too. Measured on
   the dark ground before: about 1.6:1, category label 4.2:1.
     .pdp-about-content p         main.css:20138  #333
     .pdp-selected-variant-heading main.css:7240   #242424  (variant PDPs only)
     .pdp-info-subtitle            main.css:6499   #242424
     .pdp-category-label           main.css:6104   #737373 (passes on white) */
.area-noedra .pdp-about-content p { color: var(--noedra-txt-2); }
.area-noedra .pdp-category-label { color: var(--noedra-txt-2); }
.area-noedra .pdp-selected-variant-heading,
.area-noedra .pdp-info-subtitle,
.area-noedra .product-detail--design .pdp-info-subtitle { color: var(--noedra-txt-1); }
/* enrichment section: cards on the dark ground. Tighter rhythm than the light
   PDP's 2-column card grid — the Noedra docs are 15–20 full-width bands. */
.area-noedra .product-content-blocks > .container { gap: var(--spacing-5); }
.area-noedra .product-content-blocks > .container > .cms-block { padding: var(--spacing-4) 0; }
.area-noedra .product-content-blocks > .container > .cms-block.cms-badge-row { padding-top: 0; padding-bottom: 0; }
.area-noedra .product-description-section,
.area-noedra .product-content-blocks { background: var(--noedra-bg-0); }
.area-noedra .product-content-blocks > .container > h2 { color: var(--noedra-txt-1); border-bottom-color: var(--cms-accent); }
.area-noedra .content-block { background: var(--noedra-bg-2); box-shadow: inset 0 0 0 1px var(--noedra-line); }
.area-noedra .content-block:hover { box-shadow: inset 0 0 0 1px var(--noedra-line-strong); }
.area-noedra .content-block h3,
.area-noedra .content-block h4,
.area-noedra .content-block p,
.area-noedra .content-block li,
.area-noedra .content-block th,
.area-noedra .content-block td,
.area-noedra .content-block .feature-description { color: var(--noedra-txt-1); }
/* …and the h3 half of that rule needs restating at the flyer's own
   specificity to actually win. The "flyer" pass (main.css:29712) paints every
   enrichment heading `--flyer-violet` #4f2b80 from
   `.product-content-blocks > .container > .content-block > h3` — (0,4,1),
   which out-specifies the (0,2,1) rule above, so on the dark card the
   headings rendered #4f2b80 on #161231 = 1.71:1. Measured on 19 of 35 PDPs,
   84 headings, including every configurator title (`.ncfg-title` IS an h3).
   Do NOT fix this by redefining --flyer-violet inside the area: the same
   token is a solid BACKGROUND for the violet pillar callouts
   (main.css:32872), the feature marker and `.cms-sub-brand-chip`, all of
   which read correctly on dark already. The tab labels are also fine —
   they resolve to txt-2/accent, not the violet — so they stay untouched. */
.area-noedra .product-content-blocks > .container > .content-block > h3,
.area-noedra .product-content-blocks > .container > .content-block.cms-tabs-block > h3,
.area-noedra .product-content-blocks > .container > .content-block.spec-table-block > h3,
.area-noedra .content-block.feature-highlight h3 { color: var(--noedra-txt-1); }
.area-noedra .content-block th { color: var(--noedra-txt-2); }
.area-noedra .content-block tr,
.area-noedra .content-block td,
.area-noedra .content-block th { border-color: var(--noedra-line); }
.area-noedra .content-block.callout { background: var(--noedra-bg-2); border-left-color: var(--cms-accent); }
.area-noedra .content-block.faq-block { background: var(--noedra-bg-2); }
.area-noedra .faq-question { color: var(--noedra-txt-1); }
.area-noedra .faq-answer { color: var(--noedra-txt-2); }
.area-noedra .cms-gallery-item { background: var(--noedra-bg-2); }
.area-noedra .cms-configurator-summary { background: var(--noedra-bg-2); }
.area-noedra .cms-step-marker { background: var(--cms-accent); color: var(--cms-accent-ink); }
.area-noedra .cms-footnote { color: var(--noedra-txt-3); }

/* ---- artwork on the dark ground ----------------------------------------
   Measured over all 35 PDPs: 115 image instances (31 distinct files) carry an
   opaque WHITE background, so they burn as bright rectangles on #0a0817.
   Polarity is per FILE, not per suite or per block — sampling the edge pixels
   of every rendered image gives:

     atlas_tool-icon_*   edge 0.12   already drawn for a dark ground
     node_photo_*        edge 0.33   installation photography, dark
     node_hardware_*     edge 0.94+  studio shots on white   ← burns
     *_diagram_ / _diag_ edge 0.94+  line drawings on white  ← burns

   So there is no blanket treatment: a light sheet over everything would
   destroy the Atlas icons, and `mix-blend-mode: multiply` (the usual trick for
   killing a white backdrop) crushes the subject's own dark tones, which is not
   acceptable for a parts catalogue.

   The filename prefixes ARE the content contract — the converter emits them —
   so they are what we key on. `_hardware_` + `_diagram_` + `_diag_` covers 106
   of the 115 instances; the ninth is one mis-prefixed studio render, named
   explicitly. Rather than fight the white, make it deliberate: a white sheet
   with an inset, so the art reads as a product plate or a spec document.

   The real fix is asset work (transparent backgrounds). When that lands, these
   four selectors stop matching anything and can be deleted. */
.area-noedra img[src*="_hardware_"],
.area-noedra img[src*="_diagram_"],
.area-noedra img[src*="_diag_"],
.area-noedra img[src*="-product-render"] {
  background: #ffffff;
  padding: var(--spacing-2);
  border-radius: var(--radius-lg);
  box-sizing: border-box;
}
/* The generic img plate above is for opaque art. This rule predates it and
   only ever mattered for art with real transparency, so it must not win. */
.area-noedra .cms-gallery-item img:not([src*="_hardware_"]):not([src*="_diagram_"]):not([src*="_diag_"]) {
  background: var(--noedra-bg-3);
}

/* Gallery thumbnails: the shop ships 3rem wayfinding chips (SHOP-950). In the
   area the art is 512px icons and white studio shots rather than the tall 3EL1
   portraits that drove that size, and at 3rem a subject centred in a white
   frame reads as an empty tile. Bigger, not re-cropped — `cover` is a
   deliberate choice there ("a consistent silhouette beats showing each frame
   whole") and `contain` would only shrink the subject further. */
.area-noedra .gallery-thumbnail { width: 4.5rem; height: 4.5rem; }

/* ---- catalog: the standard PLP on the dark ground ----------------------
   `/noedra/catalog` renders CatalogPage (app.dart), so the area inherits the
   shop's real PLP skeleton — .catalog-page > .pdl-header + .catalog-layout >
   .filter-panel + .catalog-content, the tile strip, the pills, the sort
   dropdown. main.css paints all of it for the LIGHT shop with literal colours,
   so the dark area re-skins it here.

   These rules were written for the bespoke browser, which imitated the PLP's
   class names under a `.noedra-catalog-plp` wrapper. The wrapper no longer
   exists (nothing renders it), so the scope is now `.area-noedra .catalog-page`
   — the real page. Deleted with the browser: `.noedra-catalog-tabs`
   (the offerings/devices tabs — devices are a `noedra_kind` facet value now),
   `.noedra-catalog-sort` (superseded by the shared `.sort-dropdown`) and
   `.noedra-catalog-family` (the devices-tab parent cards). */
/* NO `.catalog-layout { padding: 0 }` here. That rule came from the bespoke
   browser, whose markup supplied its own gutter, and carrying it over to the
   real PLP broke the page's vertical alignment: main.css gives .catalog-layout
   `padding: 0.5rem 2.5rem 0`, and that 2.5rem is what puts the filter rail on
   the same left edge (x=68 at 1880px) as the title and the rail toggle above
   it. Zeroed, the rail jumped to x=30 — 38px left of everything above it — and
   the grid's right edge ran 38px PAST the sort control. Measured against the
   light shop's /catalog, which is the reference for both. */
.area-noedra .catalog-page .filter-panel {
  background: transparent;
  box-shadow: none;
  /* under the fixed header + the area sub-nav */
  top: calc(var(--header-height) + 4.25rem);
}
/* main.css pins the header over the scrolling facet list with its own
   #ffffff — repaint with the area ground so the pin still works. */
.area-noedra .catalog-page .filter-panel-header { background: var(--noedra-bg-0); border-bottom: 1px solid var(--noedra-line); }
.area-noedra .catalog-page .filter-facet-title { color: var(--cms-text-3); }
/* the scroll-hint fade at the rail's bottom is a white gradient in main.css */
.area-noedra .catalog-page .filter-panel-body::after { background: linear-gradient(to bottom, rgba(10, 8, 23, 0), #0a0817); }
.area-noedra .catalog-page .plp-filter__form { background: var(--noedra-bg-2); border: 1px solid var(--noedra-line); }
.area-noedra .catalog-page .plp-filter__form:focus-within { border-color: var(--cms-accent); }
.area-noedra .catalog-page .plp-filter__input { background: transparent; color: var(--cms-text); }
.area-noedra .catalog-page .plp-filter__input::placeholder { color: var(--cms-text-3); }
.area-noedra .catalog-page .filter-pill { background: var(--noedra-bg-2); border-color: var(--noedra-line); color: var(--cms-text-2); }
.area-noedra .catalog-page .filter-pill:hover { border-color: var(--noedra-line-strong); color: var(--cms-text); }
.area-noedra .catalog-page .filter-pill.selected { background: var(--cms-accent-soft); border-color: var(--cms-accent); color: var(--cms-text); }
.area-noedra .catalog-page .filter-pill[disabled] { opacity: 0.45; }
.area-noedra .catalog-page .filter-pill-count { color: var(--cms-text-3); }
.area-noedra .catalog-page .filter-panel-count-badge { background: var(--noedra-bg-3); color: var(--cms-text); border: 1px solid var(--noedra-line-strong); }
.area-noedra .catalog-page .products-list-header { border: 0; background: transparent; }
.area-noedra .catalog-page .results-count { color: var(--cms-text-3); font-size: var(--font-size-sm); }
.area-noedra .catalog-page .empty-state { color: var(--cms-text-2); }
/* Chrome the bespoke browser never had, so it was never themed: the shared
   sort dropdown, the subcategory tile strip (the four suites) and the filters
   toggle button all ship literal light surfaces in main.css. */
.area-noedra .catalog-page .sort-dropdown-header,
.area-noedra .catalog-page .sort-dropdown-panel {
  background: var(--noedra-bg-2); border-color: var(--noedra-line-strong); color: var(--cms-text);
}
/* The CONTAINERS, not just their innards. main.css gives `.sort-dropdown` and
   `.view-toggle` their own white plate with a #f2f2f2 hairline, so theming only
   the header/buttons inside left two white boxes sitting on the dark ground —
   a contrast audit never catches this (dark-on-white passes), only the eye. */
.area-noedra .catalog-page .sort-dropdown,
.area-noedra .catalog-page .view-toggle {
  background: var(--noedra-bg-2); border-color: var(--noedra-line-strong);
}
.area-noedra .catalog-page .view-toggle__divider { background: var(--noedra-line-strong); }
.area-noedra .catalog-page .sort-option { color: var(--cms-text-2); }
.area-noedra .catalog-page .sort-option:hover { background: var(--noedra-bg-3); color: var(--cms-text); }
.area-noedra .catalog-page .category-tile {
  background: var(--noedra-bg-2); border-color: var(--noedra-line); color: var(--cms-text-2);
}
.area-noedra .catalog-page .category-tile:hover { border-color: var(--noedra-line-strong); color: var(--cms-text); }
.area-noedra .catalog-page .category-tile.active {
  background: var(--cms-accent-soft); border-color: var(--cms-accent); color: var(--cms-text);
}
.area-noedra .catalog-page .filters-btn {
  background: var(--noedra-bg-2); border-color: var(--noedra-line-strong); color: var(--cms-text);
}
.area-noedra .catalog-page .product-header-title { color: var(--cms-text); }
/* The PLP's own product card (`.product-card-link` from product_card.dart — NOT
   the `.cms-product-card` the CMS grids use, which this file already themes).
   It ships a white plate, and because the area remaps the text tokens to near
   white, the title landed at 1.13:1 — light-on-light, the inverse of the usual
   dark-mode failure and invisible on all 24 cards. Give the card the same dark
   surface the CMS cards get, rather than reaching in to re-darken each label. */
.area-noedra .catalog-page .product-card-link,
.area-noedra .catalog-page .product-list-container .product-card-link {
  background: var(--noedra-bg-2);
  border-color: var(--noedra-line);
  box-shadow: inset 0 0 0 1px var(--noedra-line);
}
.area-noedra .catalog-page .product-card-link:hover { box-shadow: inset 0 0 0 1px var(--noedra-line-strong); }
.area-noedra .catalog-page .product-title { color: var(--cms-text); }
.area-noedra .catalog-page .product-subtitle,
.area-noedra .catalog-page .product-description { color: var(--cms-text-2); }
.area-noedra .catalog-page .product-category-label,
.area-noedra .catalog-page .product-eyebrow { color: var(--cms-text-3); }
.area-noedra .catalog-page .product-price,
.area-noedra .catalog-page .product-price-quote { color: var(--cms-text); }
/* The card's price block. These were dark-on-WHITE and therefore fine until the
   card above became dark — turning the surface over is what exposed them, so
   they belong with that change rather than as a separate finding. "On request"
   is the price line every Noedra product shows, on all 24 cards. */
.area-noedra .catalog-page .lead-price-on-request,
.area-noedra .catalog-page .lead-price-bold { color: var(--cms-text); }
.area-noedra .catalog-page .lead-price-label { color: var(--cms-text-3); }
.area-noedra .catalog-page .product-info-text { color: var(--cms-text-2); }
/* Product photography keeps its own white plate (see the artwork section
   above): the image sits in its own wrapper, so scope the dark card background
   to the CARD and leave the media alone. */
.area-noedra .catalog-page .product-image-wrapper { background: #ffffff; }
/* Subcategory tiles: the four suites. `.category-tile` carries the surface, but
   the LABEL and COUNT inside it keep main.css's #262626 — 1.19:1 on the tile. */
.area-noedra .catalog-page .tile-label { color: var(--cms-text); }
.area-noedra .catalog-page .tile-count { color: var(--cms-text-3); }
/* Sort control: the header's own background was repainted above, but its label
   ("Sort by") and value ("Product name") are separate elements with literal
   greys. */
.area-noedra .catalog-page .sort-dropdown-label { color: var(--cms-text-3); }
.area-noedra .catalog-page .sort-dropdown-value { color: var(--cms-text); }
.area-noedra .catalog-page .sort-direction-toggle { color: var(--cms-text-2); }
/* Grid/list toggle + the infinite-scroll progress line. */
.area-noedra .catalog-page .view-toggle__btn { color: var(--cms-text-3); }
.area-noedra .catalog-page .view-toggle__btn.active { color: var(--cms-text); }
.area-noedra .catalog-page .load-more-progress { color: var(--cms-text-2); }
/* Breadcrumb trail — the trailing (current) crumb is a plain <a> with main.css's
   #242424 straight on the area ground. */
.area-noedra .catalog-page .pdl-breadcrumb-row a,
.area-noedra .catalog-page .breadcrumb a { color: var(--cms-text-3); }
.area-noedra .catalog-page .pdl-breadcrumb-row a:hover,
.area-noedra .catalog-page .breadcrumb a:hover { color: var(--cms-text); }

/* ---- landing: value arc ------------------------------------------------
   The prototype's arc cards carry a soft core-purple border and the
   tri-phrase lead ("From complexity to clarity. · …") in the core accent.
   Scoped via :has(.cms-step-dot) so only the arc (the one steps block with
   contribution dots) gets the treatment — "How buying works" stays plain. */
.area-noedra .cms-steps:has(.cms-step-dot) .cms-section-lead { color: var(--suite-core); font-weight: 600; }
.area-noedra .cms-steps--cards .cms-step:has(.cms-step-dots) { border-color: rgba(139, 110, 246, 0.28); background: var(--noedra-bg-2); }

/* ---- sub-navigation ---------------------------------------------------- */
.noedra-nav {
  position: sticky;
  top: var(--header-height);
  z-index: 20;
  background: rgba(10, 8, 23, 0.86);
  backdrop-filter: blur(0.75rem);
  border-bottom: 1px solid var(--noedra-line);
  /* Follows the auto-hiding main header (web/header.js toggles
     .site-header.header-hidden on scroll-down): the bar slides up to the
     viewport top when the header hides and back under it when it returns,
     with the header's own easing — so the area's spine is always visible. */
  transition: top 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
body:has(.site-header.header-hidden) .noedra-nav { top: 0; }
/* Embed mode (native app webview) hides the site header entirely. */
html.embedded .noedra-nav { top: 0; }
.noedra-nav-inner {
  display: flex; align-items: center; gap: var(--spacing-5);
  min-height: 3.25rem;
  overflow-x: auto; scrollbar-width: none;
}
.noedra-nav-inner::-webkit-scrollbar { display: none; }
.noedra-nav-brand {
  display: inline-flex; align-items: baseline; gap: var(--spacing-2);
  text-decoration: none; color: var(--cms-text); flex: none;
}
.noedra-nav-wordmark { font-weight: 700; font-size: var(--font-size-lg); letter-spacing: -0.01em; }
.noedra-nav-claim { font-size: 0.6rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--cms-text-3); }
.noedra-nav-suites, .noedra-nav-sections { display: flex; align-items: center; gap: var(--spacing-1); margin: 0; padding: 0; list-style: none; flex: none; }
.noedra-nav-sections { margin-left: auto; gap: var(--spacing-2); }
.noedra-nav-suite {
  display: inline-flex; align-items: center; gap: var(--spacing-2);
  padding: 0.3rem 0.65rem 0.3rem 0.35rem;
  border-radius: var(--radius-full); border: 1px solid transparent;
  color: var(--cms-text-2); text-decoration: none; font-size: var(--font-size-sm); font-weight: 600;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.noedra-nav-suite-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem; border-radius: var(--radius-sm);
  border: 1.5px solid var(--cms-accent); color: var(--cms-accent); background: var(--cms-accent-soft);
  font-size: 0.7rem; font-weight: 700;
}
/* Hover dims the label a touch (no pill background or border, which read
   as cramped; plain brightening was invisible). The full suite-accent
   treatment is reserved for the active pill. */
.noedra-nav-suite:hover { color: var(--cms-text-3); }
.noedra-nav-suite:hover .noedra-nav-suite-mark { opacity: 0.75; }
.noedra-nav-suite.is-active { border-color: var(--cms-accent); color: var(--cms-text); background: var(--cms-accent-soft); }
.noedra-nav-link {
  display: inline-block; padding: 0.4rem 0.75rem; border-radius: var(--radius-full);
  color: var(--cms-text-2); text-decoration: none; font-size: var(--font-size-sm); font-weight: 600;
  border: 1px solid transparent;
}
.noedra-nav-link:hover { color: var(--cms-text); background: var(--noedra-bg-3); }
.noedra-nav-link.is-active { color: var(--cms-text); border-color: var(--noedra-line-strong); background: var(--noedra-bg-3); }

/* ---- inline hero scene; CMS cards remain outside the SVG -------------- */
/* Landing-only spacing: suite pages retain the standard CMS hero rhythm. */
.area-noedra .cms-page-hero:has([data-scene="noedra-grid"]) {
  padding-block: 1.5rem 1rem;
}
.area-noedra .cms-page-hero:has([data-scene="noedra-grid"]) .cms-hero-band-inner {
  gap: 1.25rem;
}
.area-noedra .cms-page-hero:has([data-scene="noedra-grid"]) .cms-hero-band-heading {
  margin-bottom: 0;
}
.area-noedra .cms-hero-band-scene[data-scene="noedra-grid"] {
  position: relative;
  width: 100%;
  min-height: 0;
  container-type: inline-size;
  margin: 0 auto;
}
.area-noedra .cms-hero-band-scene[data-scene="noedra-grid"]:empty {
  aspect-ratio: 1440 / 470;
}
.area-noedra .noedra-grid-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: hidden;
}
.area-noedra .noedra-grid-svg a { text-decoration: none; }
.noedra-scene-footer {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--spacing-4);
  margin: 0;
  border-top: 1px solid var(--cms-line);
  color: var(--cms-text-3);
  font-size: var(--font-size-xs);
  letter-spacing: .1em;
}
.noedra-scene-footer > span:last-child { color: var(--suite-atlas); }
.noedra-scene-status {
  display: flex;
  align-items: center;
  gap: var(--spacing-3);
  min-height: 2.5rem;
  min-width: 0;
  letter-spacing: normal;
}
.noedra-scene-detail { flex: 1; text-align: center; margin: 0; padding: var(--spacing-2) 0; color: var(--cms-text-2); font-size: var(--font-size-xs); line-height: 1.6; }
.noedra-scene-reset { padding: var(--spacing-2); background: transparent; border: 0; color: var(--cms-text); font: inherit; font-size: var(--font-size-xs); cursor: pointer; }
.noedra-scene-reset[hidden] { display: none; }
.noedra-scene-reset:focus-visible { outline: .125rem solid var(--cms-accent); outline-offset: .25rem; }
.noedra-scene-error { color: var(--cms-text-2); }
/* Let the landing suite cards sit on the same ground as the hero. */
.area-noedra:has([data-scene="noedra-grid"]) #suites.cms-card-grid {
  background: transparent;
}
/* Shared state illuminates the existing CMS links, including all four for twin. */
.area-noedra .cms-card-grid [data-hero-active="true"],
.area-noedra .noedra-suite-strip [data-hero-active="true"] {
  border-color: var(--cms-accent);
  background: var(--cms-accent-soft);
  box-shadow: 0 0 1.25rem -.5rem var(--cms-accent);
}
.noedra-grid-svg text{font-family:var(--font-family)}.noedra-grid-svg .technical{letter-spacing:0.065625rem}.noedra-grid-svg .asset{transition:opacity .35s}.noedra-grid-svg .callout{display:none}.noedra-grid-svg .expansion-caption{letter-spacing:0.09375rem;opacity:.7;pointer-events:none}
.noedra-grid-svg .planned-asset :is(path,polygon,ellipse,circle){fill:none!important;stroke:#29c560!important;stroke-width:1.1!important;stroke-dasharray:1.4 4.2;stroke-linecap:round;stroke-linejoin:round}.noedra-grid-svg .planned-asset .turbine-hub{stroke-dasharray:none;stroke-width:1!important}
.noedra-grid-svg .security-shell{pointer-events:none}.noedra-grid-svg .security-surface{stroke:none;opacity:.8}.noedra-grid-svg .security-outline{fill:none;stroke:#b69ae9;stroke-width:.9;stroke-linecap:round;stroke-dasharray:1.3 5;opacity:.34}.noedra-grid-svg .security-rim{fill:none;stroke:#9b6bfa;stroke-width:.9;stroke-linecap:round;stroke-dasharray:1.3 5;opacity:.36}.noedra-grid-svg .security-rim-back{fill:none;stroke:#9b6bfa;stroke-width:.6;stroke-linecap:round;stroke-dasharray:1 5;opacity:.22}.noedra-grid-svg .security-reflection{fill:none;stroke:#dfcfff;stroke-width:1;stroke-linecap:round;stroke-dasharray:1 6;opacity:.04}.noedra-grid-svg .security-badge{opacity:.85}
[data-scene="noedra-grid"]:is([data-focus=shield],[data-focus=twin]) .noedra-grid-svg .security-outline{opacity:.65;stroke-width:1}[data-scene="noedra-grid"]:is([data-focus=shield],[data-focus=twin]) .noedra-grid-svg .security-rim{opacity:.65}[data-scene="noedra-grid"]:is([data-focus=shield],[data-focus=twin]) .noedra-grid-svg .security-rim-back{opacity:.32}[data-scene="noedra-grid"]:is([data-focus=shield],[data-focus=twin]) .noedra-grid-svg .security-reflection{opacity:.07}[data-scene="noedra-grid"]:is([data-focus=shield],[data-focus=twin]) .noedra-grid-svg .security-surface{opacity:1}

.noedra-grid-svg .hotspot{color:var(--accent);cursor:pointer;outline:none}.noedra-grid-svg .hotspot-ring,.noedra-grid-svg .hotspot-dot{transition:opacity .2s,stroke-width .2s,filter .2s}.noedra-grid-svg .hotspot-halo{opacity:0;transition:opacity .2s}.noedra-grid-svg .hotspot-label{opacity:0;pointer-events:none;transition:opacity .15s}.noedra-grid-svg .hotspot[data-revealed=true] .hotspot-label{opacity:1;pointer-events:auto}.noedra-grid-svg .hotspot[data-current=true] .hotspot-halo,.noedra-grid-svg .hotspot:focus-visible .hotspot-halo{opacity:1}.noedra-grid-svg .hotspot[data-current=true] .hotspot-ring{stroke-width:2}.noedra-grid-svg .hotspot[data-dimmed=true] .hotspot-ring,.noedra-grid-svg .hotspot[data-dimmed=true] .hotspot-dot{opacity:.18}.noedra-grid-svg .hotspot[data-illuminated=true] .hotspot-dot{filter:drop-shadow(0 0 0.3125rem currentColor)}.noedra-grid-svg .hotspot[data-illuminated=true] .hotspot-halo{opacity:.7}.noedra-grid-svg .hit-target{pointer-events:all}
.noedra-grid-svg .twin{cursor:pointer;outline:none;opacity:1}.noedra-grid-svg .twin[data-active=true]{filter:drop-shadow(0 0 0.5rem #9b6bfa40)}[data-scene="noedra-grid"][data-focus=twin] .noedra-grid-svg .planned-asset{filter:drop-shadow(0 0 0.25rem #29c56055)}[data-scene="noedra-grid"][data-focus=twin] .noedra-grid-svg .packet{filter:drop-shadow(0 0 0.25rem #29aaebaa)}
.noedra-grid-svg .packet{animation:noedra-travel 8s linear infinite}.noedra-grid-svg .packet.alt{animation-delay:-4s}.noedra-grid-svg .signal{animation:noedra-signal 5s ease-in-out infinite}.noedra-grid-svg .rotor{transform-box:view-box;transform-origin:0 0;animation:noedra-spin 24s linear infinite}@keyframes noedra-travel{to{stroke-dashoffset:-720}}@keyframes noedra-signal{0%,100%{opacity:.35}50%{opacity:1}}@keyframes noedra-spin{to{transform:rotate(360deg)}}
/* Cable routes and the connected-model cycle. */
.noedra-grid-svg .underground-cable{fill:none;stroke:#62a89b;stroke-width:1.05;stroke-dasharray:3 4;stroke-linecap:round;stroke-linejoin:round;opacity:.72}
.noedra-grid-svg .turbine-feed{stroke:#29c560;stroke-dasharray:2 4}
.noedra-grid-svg .cable-caption{letter-spacing:0.0625rem;opacity:.8}
.noedra-grid-svg .twin .cycle-arc{fill:none;stroke:var(--entity-color);stroke-width:1;opacity:.4}
.noedra-grid-svg .twin .cycle-packet{fill:none;stroke:var(--entity-color);stroke-width:1.7;stroke-linecap:round;stroke-dasharray:3 97;animation:noedra-cycle-flow 7s linear infinite;opacity:.7}
.noedra-grid-svg .twin .schema-port{fill:var(--entity-color);opacity:.7}
.noedra-grid-svg .twin .twin-title{letter-spacing:.08em}
.noedra-grid-svg .twin .model-label{letter-spacing:.045em}
.noedra-grid-svg .twin .shared-model{fill:#17122b;stroke:#b7a8d3;stroke-width:1}
.noedra-grid-svg .twin .shared-model ellipse{fill:#221936}
.noedra-grid-svg .twin .model-band{fill:none;stroke-width:.6;opacity:.4}
.noedra-grid-svg .twin .schema-entity rect{fill:#100d20;stroke:var(--entity-color);stroke-opacity:.45;stroke-width:.9}
.noedra-grid-svg .twin .schema-monogram{fill:var(--entity-color);font-weight:500}
.noedra-grid-svg .twin .schema-label{fill:#d2c8e2;letter-spacing:.035em}
.noedra-grid-svg .twin [data-entity][data-active=true] rect{stroke-opacity:1;fill:#211833}
.noedra-grid-svg .twin [data-entity][data-active=true] .cycle-arc{opacity:.95}
.noedra-grid-svg .twin [data-entity][data-active=true] .schema-port{opacity:1}
.noedra-grid-svg .twin:focus-visible .shared-model{stroke:#e0ceff;stroke-width:1.5}
@keyframes noedra-cycle-flow{to{stroke-dashoffset:-100}}
@media(prefers-reduced-motion:reduce){.noedra-grid-svg .twin .cycle-packet{animation:none}}

@container (max-width: 44rem) {
  .noedra-grid-svg .hotspot-label, .noedra-grid-svg .expansion-caption, .noedra-grid-svg .cable-caption { display: none; }
  .noedra-grid-svg .hotspot .hit-target { r: 1.75rem; }
  .noedra-scene-footer { grid-template-columns: 1fr auto; font-size: .55rem; gap: .25rem var(--spacing-2); letter-spacing: .05em; padding-top: var(--spacing-2); }
  .noedra-scene-status { grid-column: 1 / -1; order: 1; min-height: 3.75rem; }
  .noedra-scene-detail { text-align: left; }
}
@media (prefers-reduced-motion: reduce) {
  .noedra-grid-svg *, .noedra-scene-status *, [data-hero-active] { animation: none !important; transition: none !important; }
}
