@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

@font-face {
  font-family: 'Dorsa';
  src: url('assets/fonts/Dorsa-Regular.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Mount';
  src: url('assets/fonts/Mount.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

/* ============================================================
   NO VISIBLE SCROLLBARS — anywhere.
   Applied globally (not per-component) so that any element which becomes
   scrollable never sprouts a bar. Scrolling itself still works; only the
   chrome is suppressed.
   ============================================================ */
* {
  scrollbar-width: none;
  -ms-overflow-style: none;
}

*::-webkit-scrollbar {
  display: none;
}

/* ============================================================
   DESIGN TOKENS
   --sr-* tokens are managed live from /siriahagent: theme-agent.js overrides
   them at runtime from persisted state. Declared once in config/theme-schema.js.
   LS = landscape, PT = portrait.
   Every size, space and corner below is a percentage of the window (vw/svh),
   never a pixel — that is what lets one layout hold in landscape, portrait and
   at any window size. Pixels remain only for hairlines (1px borders), which do
   not scale by design.
   ============================================================ */
:root {
  --color-bg: #0a0d16;
  --color-surface-solid: #141826;
  --color-surface: color-mix(in srgb, var(--color-surface-solid) 70%, transparent);
  --color-surface-hover: color-mix(in srgb, var(--color-surface-solid) 85%, transparent);
  --color-text-primary: #edeff5;
  --color-text-secondary: #9ca3b8;
  --color-text-muted: #565d75;
  --color-border-base: #ffffff;
  --color-border: color-mix(in srgb, var(--color-border-base) 8%, transparent);
  --color-border-focus: hsl(var(--accent-h) var(--accent-s) var(--accent-l) / 0.4);

  /* Primary accent: h/s/l driven by --accent-h/-s/-l (extracted from accentPrimary) so it can
     still drift circadianly on --accent-h while the agent controls saturation/lightness per theme. */
  --accent-h: 246;
  --accent-s: 81%;
  --accent-l: 69%;
  --color-accent-blue: hsl(var(--accent-h) var(--accent-s) var(--accent-l));
  --color-accent-blue-glow: color-mix(in srgb, var(--color-accent-blue) 15%, transparent);

  /* Secondary accent: agent-controlled directly (no hue formula) */
  --color-accent-violet: #b26ff0;
  --color-accent-violet-glow: color-mix(in srgb, var(--color-accent-violet) 15%, transparent);

  /* Status Colors */
  --color-status-available: #34d399;
  --color-status-reserved: #fbbf24;
  --color-status-unavailable: #fb7185;
  --color-status-pending: #c084fc;

  --font-primary: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --transition-smooth: all 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
  --transition-fast: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);

  /* Siriah agent tokens (live-themable) */
  --sr-sel-scale: 1.3;

  /* Corners: one radius per surface role, so every rounded box in the app is
     reachable from four controls. vw, not %, because a percentage radius
     resolves against each box's own width and height — the same value would
     round a wide button into an ellipse and a square card into a circle.
     Deliberate circles (.cart-badge, .contact-icon) keep their own 50%. */
  --sr-rad-window-ls: 1.25vw;
  --sr-rad-window-pt: 3.5vw;
  --sr-rad-cell-ls: 0.9vw;
  --sr-rad-cell-pt: 2.5vw;
  --sr-rad-control-ls: 0.5vw;
  --sr-rad-control-pt: 1.75vw;
  --sr-rad-small-ls: 0.3vw;
  --sr-rad-small-pt: 1vw;

  /* Titles: two roles cover every heading in the app — the one that names a
     view, and the one that heads a card/modal/dialog/admin panel. All titles
     are uppercase, so tracking is an em (proportional to whichever size the
     role resolves to) rather than a fixed nudge per rule. */
  --sr-title-view-ls: 2.2vw;
  --sr-title-view-pt: 6vw;
  --sr-title-panel-ls: 1.25vw;
  --sr-title-panel-pt: 4.2vw;
  --sr-title-label-ls: 1vw;
  --sr-title-label-pt: 3.4vw;
  /* Ceilings in viewport height: a width-derived size tuned for a phone is
     enormous on a tablet in portrait (6vw = 22px at 375 wide, 50px at 834).
     The smaller of the two wins, so width drives phones and height caps
     anything larger — the old clamp(), in percentages instead of pixels. */
  --sr-title-view-max: 3.8svh;
  --sr-title-panel-max: 2.2svh;
  --sr-title-label-max: 1.8svh;
  --sr-title-track: 0.1em;
  --sr-title-weight: 500;

  /* Spacing/frame tokens are percentages of the main window — vw for widths,
     svh for the nav height — so every dimension scales with the viewport on any
     device instead of being pinned to one assumed screen size. svh rather than vh
     keeps the header from shifting as a mobile URL bar collapses. */
  --sr-pad-ls: 1.9vw;
  --sr-gap-ls: 1.1vw;
  --sr-txt-ls: 1.0;
  --sr-btn-ls: 1.0;
  --sr-frm-ls: 1.25vw;
  --sr-nav-ls: 8svh;
  --sr-window-w-ls: 86%;
  --sr-window-h-ls: 100%;
  --sr-logo-ls: 1.0;
  /* Nav corner brand mark (hexagon + wordmark, upper-left) — independent of --sr-logo above */
  --sr-navhex-ls: 1.0;
  --sr-navword-ls: 1.0;
  --sr-navgap-ls: 0.8vw;


  --sr-menuicon-ls: 2.4svh;
  --sr-menutext-ls: 1;
  --sr-menugap-ls: 0.3vw;

  --sr-pad-pt: 3vw;
  --sr-gap-pt: 2.6vw;
  --sr-txt-pt: 0.92;
  --sr-btn-pt: 0.9;
  --sr-frm-pt: 2.6vw;
  --sr-nav-pt: 8.5svh;
  --sr-logo-pt: 0.85;
  --sr-window-w-pt: 100%;
  --sr-window-h-pt: 100%;
  --sr-navhex-pt: 1.0;
  --sr-navword-pt: 1.0;
  --sr-navgap-pt: 2vw;
  --sr-menuicon-pt: 3svh;
  --sr-menutext-pt: 1;
  --sr-menugap-pt: 1vw;

  /* ---- Floating windows: section panels, modals, dialogs, drawers ----
     Shadow offset is derived from a size + an angle so the agent can aim the
     light source; 0deg casts straight down and rotates clockwise. */
  --sr-window-color: #ffffff;
  --sr-window-opacity: 92%;
  --sr-window-shadow-size: 2.4vw;
  --sr-window-shadow-color: #2a1b33;
  --sr-window-shadow-angle: 0deg;
  --sr-window-pad-ls: 1.9vw;
  --sr-window-pad-pt: 3vw;
  /* Frosted-glass strength behind every floating surface. Percent of window
     width, so the effect stays proportional instead of being a fixed pixel
     radius that reads as heavy glass on a phone and thin on a desktop. */
  --sr-window-blur: 1.9vw;

  /* ---- Floating cells: philosophy / product / admin cards ---- */
  --sr-cell-color: #ffffff;
  --sr-cell-opacity: 70%;
  --sr-cell-shadow-size: 0.6vw;
  --sr-cell-shadow-color: #2a1b33;
  --sr-cell-shadow-angle: 0deg;
  --sr-cell-pad-ls: 1.15vw;
  --sr-cell-pad-pt: 3vw;

  /* ---- Navbar: the fixed top bar's own surface ---- */
  --sr-navbar-color: #d9cff2;
  --sr-navbar-opacity: 40%;
  --sr-navbar-blur: 1.6vw;

  /* Validation: the ring drawn round a field the reader still has to fill.
     Colour comes from Status > Bad, so it follows the global set. */
  --sr-alert-ring: 0.16vw;
  --sr-alert-strength: 55%;

  /* Privacy gate brand mark */
  --sr-gatelogo-ls: 16svh;
  --sr-gatelogo-pt: 11svh;

  /* ---- Scrim: the dimmed backdrop behind modals and dialogs ---- */
  --sr-scrim-color: #2a1b33;
  --sr-scrim-opacity: 70%;
  --sr-scrim-blur: 1.1vw;

  /* Dropdown surface: shared by the closed trigger and the open list, so a menu
     reads as one object opening rather than two boxes in two greys. */
  --sr-dropdown-color: #4f2965;
  --sr-dropdown-opacity: 4%;
  /* The chosen value is not its own colour decision — it IS the accent, the
     same one an active nav item and an active category tab use. Bound to the
     live variable rather than copied, so it also follows the circadian hue
     drift navigation.js applies through the day. A separate agent control here
     would look identical at one hour and mismatched at another. */
  --sr-dropdown-chosen: var(--color-accent-blue);
  --sr-dropdown-text: #6b5578;

  /* Footprint of the floating cart trigger in portrait. Declared once because
     both the button and the lane the header reserves for it must agree. */
  --sr-cart-size: max(var(--sr-tap-min), 11vw);

  /* ---- Buttons ---- */
  --sr-button-color: #7a00cc;
  --sr-button-opacity: 100%;
  --sr-button-shadow-size: 0.3vw;
  --sr-button-shadow-color: #2a1b33;
  --sr-button-shadow-angle: 0deg;

  /* Accessible minimum touch target. Kept absolute on purpose: the tokens above stay
     pure percentages, and only this floor prevents a narrow window from shrinking a
     control below tappable size. */
  --sr-tap-min: 44px;

  /* Legibility floor for small type, same category as the touch target above and
     absolute for the same reason. A width-derived size has a ceiling (the
     *-max tokens) but nothing stops it shrinking: the label role is 1vw, which
     is a correct 12.8px at 1280 wide but an unreadable 7.5px at 752. Uppercase
     tracked text does not survive below this, at any viewport. */
  --sr-text-floor: 11px;

  /* ============================================================
     STACKING SCALE — two tiers, because .app-container carries its own
     z-index and therefore forms a stacking context. Anything inside it is
     painted within the app band no matter how large its own z-index is, so
     mixing the two tiers' numbers is what makes ad-hoc values misleading.

     ROOT TIER — direct children of <body>; these numbers genuinely compete.
     Spaced by 1000 so new layers can be inserted without renumbering. */
  --z-ambient: 0;      /* .bg-ambient background art        */
  --z-app: 1;          /* .app-container (nav + all views)   */
  --z-drawer: 2000;    /* product & cart side drawers        */
  --z-scrim: 3000;     /* modal / dialog backdrops           */
  --z-toast: 4000;     /* transient messages                 */
  --z-gate: 9000;      /* privacy gate — must cover all      */

  /* LOCAL TIER — inside .app-container. Values only rank against each other;
     none of them can rise above a root-tier layer, which is exactly why the
     drawers/scrims above are body-level rather than nested. */
  --z-view-idle: 1;    /* .view-section, inactive            */
  --z-view: 10;        /* .view-section.active               */
  --z-sticky: 20;      /* booking footer pinned in a panel   */
  --z-popover: 30;     /* field pickers, language menu       */
  --z-floating: 40;    /* cart FAB, logout — sit below the bar */
  --z-navbar: 50;      /* fixed top bar, above all content     */
  --z-over-navbar: 60; /* the few controls that must clear the bar
                          (admin exit overlaps the bar's band)  */

  /* Room a shadow needs outside its box: offset (1x size) plus half the blur
     (blur is 2x size). box-shadow never contributes to scroll extent, so without
     reserving this, shadows are clipped at any scroll boundary.
     Split per purpose: reserving the large window extent around small cells was
     insetting the product list by ~100px a side for no reason. */
  --sr-window-room: calc(var(--sr-window-shadow-size) * 2);
  --sr-cell-room: calc(var(--sr-cell-shadow-size) * 2);
  --sr-button-room: calc(var(--sr-button-shadow-size) * 2);
  --sr-shadow-room: max(var(--sr-window-room), var(--sr-cell-room), var(--sr-button-room));

  /* Resolved per orientation */
  --sr-pad: var(--sr-pad-ls);
  --sr-gap: var(--sr-gap-ls);
  --sr-txt: var(--sr-txt-ls);
  --sr-btn: var(--sr-btn-ls);
  --sr-frm: var(--sr-frm-ls);
  --sr-nav: var(--sr-nav-ls);
  --sr-window-w: var(--sr-window-w-ls);
  --sr-window-h: var(--sr-window-h-ls);
  --sr-logo: var(--sr-logo-ls);
  --sr-navhex: var(--sr-navhex-ls);
  --sr-navword: var(--sr-navword-ls);
  --sr-navgap: var(--sr-navgap-ls);
  --sr-menuicon: var(--sr-menuicon-ls);
  --sr-menutext: var(--sr-menutext-ls);
  --sr-menugap: var(--sr-menugap-ls);
  --sr-window-pad: var(--sr-window-pad-ls);
  --sr-cell-pad: var(--sr-cell-pad-ls);
  --sr-rad-window: var(--sr-rad-window-ls);
  --sr-rad-cell: var(--sr-rad-cell-ls);
  --sr-rad-control: var(--sr-rad-control-ls);
  --sr-rad-small: var(--sr-rad-small-ls);
  --sr-title-view: var(--sr-title-view-ls);
  --sr-title-panel: var(--sr-title-panel-ls);
  --sr-title-label: var(--sr-title-label-ls);
  --sr-gatelogo: var(--sr-gatelogo-ls);

  /* ---- Composed surfaces & shadows ----
     Built once here so every floating element shares one definition and the agent
     only ever touches the inputs above. sin/cos turn the angle + size into an
     x/y offset; blur scales with size so a bigger shadow also softens. */
  --sr-window-bg: color-mix(in srgb, var(--sr-window-color) var(--sr-window-opacity), transparent);
  --sr-window-shadow:
    calc(sin(var(--sr-window-shadow-angle)) * var(--sr-window-shadow-size))
    calc(cos(var(--sr-window-shadow-angle)) * var(--sr-window-shadow-size))
    calc(var(--sr-window-shadow-size) * 2)
    color-mix(in srgb, var(--sr-window-shadow-color) 45%, transparent);

  --sr-cell-bg: color-mix(in srgb, var(--sr-cell-color) var(--sr-cell-opacity), transparent);
  --sr-cell-shadow:
    calc(sin(var(--sr-cell-shadow-angle)) * var(--sr-cell-shadow-size))
    calc(cos(var(--sr-cell-shadow-angle)) * var(--sr-cell-shadow-size))
    calc(var(--sr-cell-shadow-size) * 2)
    color-mix(in srgb, var(--sr-cell-shadow-color) 35%, transparent);

  --sr-dropdown-bg: color-mix(in srgb, var(--sr-dropdown-color) var(--sr-dropdown-opacity), transparent);
  /* The open list lays that tint over the window colour: the trigger gets the
     tint against the window it sits on, so the list must reproduce both to
     match it — and stays legible over whatever content it covers. */
  --sr-dropdown-panel:
    linear-gradient(var(--sr-dropdown-bg), var(--sr-dropdown-bg)),
    var(--sr-window-bg);

  --sr-navbar-bg: color-mix(in srgb, var(--sr-navbar-color) var(--sr-navbar-opacity), transparent);
  --sr-scrim-bg: color-mix(in srgb, var(--sr-scrim-color) var(--sr-scrim-opacity), transparent);

  --sr-button-bg: color-mix(in srgb, var(--sr-button-color) var(--sr-button-opacity), transparent);
  /* Soft variant for secondary/accent buttons: a quarter of the solid fill's alpha */
  --sr-button-bg-soft: color-mix(in srgb, var(--sr-button-color) calc(var(--sr-button-opacity) * 0.25), transparent);
  --sr-button-shadow:
    calc(sin(var(--sr-button-shadow-angle)) * var(--sr-button-shadow-size))
    calc(cos(var(--sr-button-shadow-angle)) * var(--sr-button-shadow-size))
    calc(var(--sr-button-shadow-size) * 2)
    color-mix(in srgb, var(--sr-button-shadow-color) 30%, transparent);
}

@media (orientation: portrait) {
  :root {
    --sr-pad: var(--sr-pad-pt);
    --sr-gap: var(--sr-gap-pt);
    --sr-txt: var(--sr-txt-pt);
    --sr-btn: var(--sr-btn-pt);
    --sr-frm: var(--sr-frm-pt);
    --sr-nav: var(--sr-nav-pt);
    --sr-window-w: var(--sr-window-w-pt);
    --sr-window-h: var(--sr-window-h-pt);
    --sr-logo: var(--sr-logo-pt);
    --sr-navhex: var(--sr-navhex-pt);
    --sr-navword: var(--sr-navword-pt);
    --sr-navgap: var(--sr-navgap-pt);
    --sr-menuicon: var(--sr-menuicon-pt);
    --sr-menutext: var(--sr-menutext-pt);
    --sr-menugap: var(--sr-menugap-pt);
    --sr-window-pad: var(--sr-window-pad-pt);
    --sr-cell-pad: var(--sr-cell-pad-pt);
    --sr-rad-window: var(--sr-rad-window-pt);
    --sr-rad-cell: var(--sr-rad-cell-pt);
    --sr-rad-control: var(--sr-rad-control-pt);
    --sr-rad-small: var(--sr-rad-small-pt);
    --sr-title-view: var(--sr-title-view-pt);
    --sr-title-panel: var(--sr-title-panel-pt);
    --sr-title-label: var(--sr-title-label-pt);
    --sr-gatelogo: var(--sr-gatelogo-pt);
  }
}

/* Global text scale: every rem-based size in the site follows it */
html {
  font-size: calc(16px * var(--sr-txt));
}

/* --- RESET & BASE --- */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  user-select: none;
  /* Safari and older WebKit ignore the unprefixed property. */
  -webkit-user-select: none;
  /* Kills the browser's own tap flash — a hard blue rectangle from outside the
     palette that fires on every tap of a button, tab or picker. Feedback for a
     press belongs to the component's :active state, in the theme's colours. */
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
}

/* Text the reader can actually select: the fields they are filling in. The
   global rule above turns selection off everywhere so chrome cannot be
   highlighted by a stray drag, but an input is content, not chrome. */
input,
textarea {
  user-select: text;
  -webkit-user-select: text;
}

/* On-brand selection rather than the browser's blue. */
::selection {
  background: color-mix(in srgb, var(--color-accent-blue) 28%, transparent);
  color: var(--color-text-primary);
}

*,
*::before,
*::after {
  outline: 0;
}

button,
[role="button"] {
  border: 0;
  box-shadow: none;
  cursor: pointer;
}

body,
html {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background-color: var(--color-bg);
  color: var(--color-text-primary);
  font-family: var(--font-primary);
  font-weight: 300;
  letter-spacing: -0.01em;
}

/* Scrollbar styling for internal scrollable elements */
/* Any internal scroll area: reserve the same shadow room at the end of the
   scroll so shadowed cells in the last row aren't clipped. */
.scroll-custom {
  overflow-y: auto;
  padding-bottom: var(--sr-shadow-room);
}

.scroll-custom::-webkit-scrollbar {
  display: none;
}

/* State utilities toggled from JS */
.u-hidden {
  display: none !important;
}

.btn-block {
  width: 100%;
}

/* --- BACKGROUND EMANATION EFFECT --- */
.bg-ambient {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: var(--z-ambient);
  pointer-events: none;
  overflow: hidden;
  background: radial-gradient(circle at 10% 10%, color-mix(in srgb, var(--color-accent-blue) 4%, transparent) 0%, transparent 40%),
    radial-gradient(circle at 90% 80%, color-mix(in srgb, var(--color-accent-violet) 5%, transparent) 0%, transparent 45%),
    var(--color-bg);
}

/* --- APP WRAPPER --- */
.app-container {
  position: relative;
  width: 100vw;
  height: 100vh;
  z-index: var(--z-app);
  display: flex;
  flex-direction: column;
  /* Cross-fade for the language swap. Only the app content dissolves — the
     ambient background sits below at --z-ambient and holds steady, so the
     change reads as the text turning over rather than the page reloading.
     Duration is mirrored by SWAP_MS in js/i18n.js. */
  transition: opacity 0.18s ease;
}

/* Held for one swap while the DOM is retranslated underneath. Layout is
   untouched, so nothing reflows and the open view stays exactly where it was. */
.app-container.lang-swap {
  opacity: 0;
}

/* --- NAVIGATION MENU --- */
.nav-menu {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--sr-nav);
  min-height: var(--sr-tap-min);
  z-index: var(--z-navbar);
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* Window-relative, with only a lower floor — no upper cap, so the bar keeps
     breathing on large screens instead of pinning to a fixed rem value. */
  padding: 0 max(0.6rem, var(--sr-pad));
  background: var(--sr-navbar-bg);
  backdrop-filter: blur(var(--sr-navbar-blur));
  -webkit-backdrop-filter: blur(var(--sr-navbar-blur));
  transition: var(--transition-smooth);
}

.nav-menu.is-hidden {
  opacity: 0;
  pointer-events: none;
}

/* The brand mark is the home button (there is no separate INICIO link). */
.nav-brand {
  display: flex;
  align-items: center;
  gap: var(--sr-navgap, 0.8vw);
  cursor: pointer;
  color: var(--color-text-primary);
  text-decoration: none;
  transition: opacity 0.3s ease, transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.nav-brand:hover {
  opacity: 0.72;
}

.nav-brand:active {
  transform: scale(0.97);
}

.nav-brand:focus-visible {
  outline: 1px solid var(--color-border-focus);
  outline-offset: 4px;
  border-radius: var(--sr-rad-control);
}

.nav-brand .siriah-wordmark {
  /* Pre-cropped export (assets/siriahdam.svg) — width follows its own
     aspect ratio (~3.08:1), only height is set. */
  height: calc(clamp(15px, 2vh, 19px) * var(--sr-navword, 1));
  width: auto;
  display: block;
}

.nav-brand .logo-mini {
  width: calc(clamp(28px, 4vh, 36px) * var(--sr-navhex, 1) * 0.7070707);
  height: calc(clamp(28px, 4vh, 36px) * var(--sr-navhex, 1));
  display: block;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  list-style: none;
}

/* Menu item: icon on top, label centred beneath — same structure in both
   orientations, sized entirely from the agent's menu tokens. */
.nav-link {
  font-size: calc(0.66rem * var(--sr-menutext, 1));
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: color 0.3s ease, transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), font-weight 0.25s ease;
  padding: 4px 6px;
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--sr-menugap, 0.3vw);
  line-height: 1.15;
  min-width: var(--sr-tap-min);
}

.nav-link:hover {
  color: var(--color-accent-blue);
  transform: scale(1.08);
}

.nav-link.active {
  color: var(--color-accent-blue);
  font-weight: 600;
  transform: scale(1.16);
}

.nav-link-admin {
  color: var(--color-accent-blue);
}

/* ============================================================
   ICON SYSTEM
   js/icons.js mounts inline SVG into [data-icon] placeholders.
   Sized in em so every icon tracks the --sr-txt text scale and the
   agent's live tuning without needing tokens of its own.
   ============================================================ */
.icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  line-height: 0;
}

.icon svg {
  width: 1em;
  height: 1em;
  display: block;
  /* Strokes must not thicken when an icon is scaled by a parent transform
     (e.g. .nav-link.active) — keep the optical weight constant. */
  vector-effect: non-scaling-stroke;
}

/* Sized from the window, not from the label's font size — so the glyph stays
   legible independently of how small the label is set.
   Bounded at both ends on purpose: a glyph is content, not a frame. A pure vw
   value balloons on any wide-but-tall window (a 830px-wide portrait tablet made
   5.6vw a 46px icon), so the agent's value drives the middle of a clamp. */
.nav-icon {
  /* Height-relative (svh), so one value holds across a 390px phone and an 830px
     portrait tablet. The ceiling is far above any sane authored value on purpose:
     a ceiling that bites silently swallows the agent's control. */
  font-size: clamp(14px, var(--sr-menuicon, 2.4svh), 44px);
  color: currentColor;
}

/* Glyph inside a circular icon button (cart trigger) */
.btn-icon {
  font-size: 1.25rem;
}

/* Philosophy cards: glyph above the title, giving each card a visual anchor
   instead of four near-identical blocks of text */
.philosophy-card .card-icon {
  /* flex, not inline-flex — the glyph takes its own row above the title */
  display: flex;
  justify-content: flex-start;
  font-size: 1.45em;
  color: var(--color-accent-blue);
  margin-bottom: 0.55em;
  opacity: 0.92;
}

.philosophy-card:hover .card-icon {
  opacity: 1;
}

/* --- LANGUAGE SWITCHER --- */
.lang-switcher {
  position: relative;
  list-style: none;
}

.lang-switcher-trigger {
  background: var(--sr-dropdown-bg);
  color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--sr-rad-control);
  padding: 5px 9px;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 1px;
  cursor: pointer;
  transition: var(--transition-fast);
}

.lang-switcher-trigger:hover {
  color: var(--color-text-primary);
  background: color-mix(in srgb, var(--color-text-primary) 10%, transparent);
}

.lang-switcher-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  background: var(--sr-dropdown-panel);
  backdrop-filter: blur(var(--sr-window-blur));
  -webkit-backdrop-filter: blur(var(--sr-window-blur));
  border: 1px solid var(--color-border);
  border-radius: var(--sr-rad-window);
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 64px;
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity 180ms ease, transform 180ms ease;
  box-shadow: var(--sr-window-shadow);
  z-index: var(--z-popover);
}

.lang-switcher.open .lang-switcher-menu {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.lang-switcher-option {
  background: none;
  color: var(--color-text-secondary);
  padding: 6px 10px;
  border-radius: var(--sr-rad-small);
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 1px;
  text-align: left;
  cursor: pointer;
  transition: var(--transition-fast);
}

.lang-switcher-option:hover {
  background: color-mix(in srgb, var(--color-text-primary) 8%, transparent);
  color: var(--color-text-primary);
}

.lang-switcher-option.active {
  color: var(--color-accent-blue);
  font-weight: 700;
}

/* --- SCENE CONTAINER (FULLSCREEN SECTIONS) --- */
.scene-container {
  position: relative;
  flex: 1;
  width: 100%;
  height: 100%;
  /* Vertical scrolling stays native and smooth; horizontal movement is left to the
     swipe-navigation gesture in js/navigation.js. */
  touch-action: pan-y;
}

.view-section {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding-bottom: clamp(1rem, 3vh, 2rem);
  display: flex;
  justify-content: center;
  align-items: center;
  opacity: 0;
  transform: scale(0.97) translateY(15px);
  filter: blur(12px);
  pointer-events: none;
  visibility: hidden;
  z-index: var(--z-view-idle);
  transition: opacity 0.8s cubic-bezier(0.25, 1, 0.3, 1),
    transform 0.8s cubic-bezier(0.25, 1, 0.3, 1),
    filter 0.8s cubic-bezier(0.25, 1, 0.3, 1),
    z-index 0s 0.8s;
}

.view-section.active {
  opacity: 1;
  transform: scale(1) translateY(0);
  filter: blur(0px);
  pointer-events: all;
  visibility: visible;
  z-index: var(--z-view);
  transition: opacity 0.8s cubic-bezier(0.25, 1, 0.3, 1),
    transform 0.8s cubic-bezier(0.25, 1, 0.3, 1),
    filter 0.8s cubic-bezier(0.25, 1, 0.3, 1),
    z-index 0s 0s;
}

/* Room for the nav, panel-friendly scrolling.
   padding-bottom reserves --sr-shadow-room: a scroll container's scrollable
   extent ignores box-shadow entirely, so without it the panel's shadow is
   sheared off at the end of the scroll. Sides get the same guarantee. */
.view-section:not(#viewPortada) {
  padding-top: calc(var(--sr-nav) + var(--sr-gap));
  align-items: flex-start;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-left: max(clamp(10px, 2.5vw, 24px), var(--sr-window-room));
  padding-right: max(clamp(10px, 2.5vw, 24px), var(--sr-window-room));
  /* Padding, not just shadow room: with Window Shadow > Size at 0 the reserved
     room collapses to nothing and the window runs into the bottom edge. The
     clearance a floating panel needs is a layout decision, so it falls back to
     the orientation's own padding. */
  padding-bottom: max(var(--sr-pad), var(--sr-shadow-room));
}

/* --- SECTION CARD / LAYOUT TEMPLATES --- */
.section-panel {
  display: grid;
  grid-template-columns: 1fr;
}

/* THE WINDOW SURFACE — one definition for every view.
   Artículos and Cursos used to be bare layout containers with no surface at
   all: their cards floated straight on the page background while Inicio and
   Contacto sat on a window. They are the same object and now say so once.
   Footprint is Window w/h with deliberately no cap: at 100% the window must be
   able to meet the edge of the view, which a min(96vw, …) ceiling prevented. */
.section-panel,
.articles-layout {
  width: var(--sr-window-w);
  height: var(--sr-window-h);
  min-height: 0;
  margin-inline: auto;
  position: relative;
  overflow: visible;
  background: var(--sr-window-bg);
  border-radius: var(--sr-rad-window);
  backdrop-filter: blur(var(--sr-window-blur));
  -webkit-backdrop-filter: blur(var(--sr-window-blur));
  box-shadow: var(--sr-window-shadow);
}

.section-panel-split {
  grid-template-columns: 1.1fr 0.9fr;
}

@media (max-width: 900px) {
  .section-panel-split {
    grid-template-columns: 1fr;
  }
}

.panel-content {
  padding: var(--sr-window-pad);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  height: 100%;
}

.panel-cta-row {
  margin-top: 2rem;
}

.panel-media {
  background: linear-gradient(135deg, color-mix(in srgb, var(--color-accent-blue) 8%, transparent) 0%, color-mix(in srgb, var(--color-accent-violet) 5%, transparent) 100%);
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 3rem;
  position: relative;
  overflow: hidden;
}

@media (max-width: 900px) {
  .panel-media {
    display: none;
    /* Hide on smaller screens to maximize area */
  }
}

/* --- TYPOGRAPHY --- */
h1,
h2,
h3,
h4 {
  font-weight: 300;
  letter-spacing: -0.02em;
}

/* Used for the admin sidebar's brand mark and the payment modal's section
   dividers. Type comes from the label role below; this rule only positions it. */
.section-title-tag {
  color: var(--color-accent-blue);
  margin-bottom: 1.2vh;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
}

/* ---- TITLES -------------------------------------------------------------
   Every heading in the app is one of two roles, and both are agent-managed.
   Before this there were nine near-identical rules that had drifted apart:
   three sizes for the same view title (2.5rem / 1.5rem / 1.5rem) and six
   different trackings for the same panel title. Size comes from the Titles
   group per orientation; tracking is em so it follows the size; all titles
   are uppercase, which is what the tracking is there to make readable.
   Multiplying by --sr-txt keeps them tied to the Landscape/Portrait Text
   control, so type still scales as one system. */
.section-title,
.auth-title,
.articles-title {
  font-size: max(calc(min(var(--sr-title-view), var(--sr-title-view-max)) * var(--sr-txt)), var(--sr-text-floor));
  font-weight: var(--sr-title-weight);
  letter-spacing: var(--sr-title-track);
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--color-text-primary);
}

.calendar-title,
.cart-title,
.modal-title,
.dialog-title,
.admin-card-title {
  font-size: max(calc(min(var(--sr-title-panel), var(--sr-title-panel-max)) * var(--sr-txt)), var(--sr-text-floor));
  font-weight: var(--sr-title-weight);
  letter-spacing: var(--sr-title-track);
  text-transform: uppercase;
  color: var(--color-text-primary);
}

/* Third role: the small uppercase heading inside a cell, the labels in a detail
   block, and the dividers inside the payment modal. Colour is left to each
   rule — the role fixes the type, not the palette. */
.philosophy-card h3,
.contact-details h4,
.section-title-tag {
  font-size: max(calc(min(var(--sr-title-label), var(--sr-title-label-max)) * var(--sr-txt)), var(--sr-text-floor));
  font-weight: var(--sr-title-weight);
  letter-spacing: var(--sr-title-track);
  text-transform: uppercase;
}

.section-title {
  margin-bottom: 1.5rem;
}

.section-title .hl {
  color: var(--color-text-primary);
}

.section-desc {
  font-size: clamp(0.85rem, 1.5vw, 0.95rem);
  line-height: 1.7;
  color: var(--color-text-secondary);
  margin-bottom: clamp(1rem, 2.4vh, 1.5rem);
}

/* --- BUTTONS & CONTROLS ---
   Flat borderless surfaces: translucent white for neutral actions,
   translucent accent blue for primary/accent actions. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 0;
  padding: calc(12px * var(--sr-btn)) calc(28px * var(--sr-btn));
  border-radius: var(--sr-rad-control);
  background: color-mix(in srgb, var(--color-text-primary) 4%, transparent);
  color: var(--color-text-secondary);
  font-size: clamp(0.75rem, 1.2vw, 0.85rem);
  font-weight: 500;
  letter-spacing: 2px;
  text-transform: uppercase;
  cursor: pointer;
  transition: var(--transition-fast);
}

.btn:hover {
  background: color-mix(in srgb, var(--color-text-primary) 6.5%, transparent);
}

.btn-primary {
  background: var(--sr-button-bg);
  color: var(--color-bg);
  box-shadow: var(--sr-button-shadow);
}

.btn-primary:hover {
  background: color-mix(in srgb, var(--color-accent-blue) 88%, var(--color-text-primary));
  box-shadow: 0 0 15px var(--color-accent-blue-glow);
}

.btn-accent {
  background: var(--sr-button-bg-soft);
  color: var(--color-text-primary);
  box-shadow: var(--sr-button-shadow);
}

.btn-accent:hover {
  background: color-mix(in srgb, var(--color-accent-blue) 30%, transparent);
}

.btn-compact {
  padding: 8px 16px;
  font-size: 0.75rem;
}

/* Inputs & Form Elements */
.form-group {
  margin-bottom: var(--sr-frm);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-group-loose {
  margin-bottom: 1.5rem;
}

.form-group-tight {
  margin-bottom: 0.5rem;
}

/* Field labels and the tertiary auth actions are one treatment, from the Titles
   > Label role — same size, tracking, weight and case. They differ only in
   colour, which is what separates a label from something you can press. */
.form-label,
.auth-link {
  font-size: max(calc(min(var(--sr-title-label), var(--sr-title-label-max)) * var(--sr-txt)), var(--sr-text-floor));
  text-transform: uppercase;
  letter-spacing: var(--sr-title-track);
  font-weight: var(--sr-title-weight);
}

.form-label,
.auth-link {
  color: var(--color-accent-blue);
}

.input-field {
  background: color-mix(in srgb, var(--color-bg) 50%, transparent);
  border: 0;
  color: var(--color-text-secondary);
  padding: 12px 16px;
  border-radius: var(--sr-rad-control);
  font-family: var(--font-primary);
  font-size: 0.9rem;
  font-weight: 300;
  transition: var(--transition-fast);
  width: 100%;
}

.input-field::placeholder {
  color: var(--color-text-muted);
}

/* Password reveal. The wrapper exists so the button can be anchored to the FIELD
   rather than the .form-group, which also holds the label. Built in password.js
   for every input[type="password"], so the gate, the booking login and the card
   CVV all get the same control. */
.input-reveal {
  position: relative;
  display: block;
  width: 100%;
}

/* Room for the glyph, so typed text never runs underneath it. */
.input-reveal .input-field {
  padding-right: 3.2em;
}

.input-reveal-btn {
  position: absolute;
  top: 50%;
  right: 0.9em;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  background: none;
  padding: 0;
  color: var(--color-text-muted);
  /* Sized in em like every other icon, so it follows --sr-txt and the agent. */
  font-size: 1.05em;
  transition: var(--transition-fast);
}

.input-reveal-btn:hover {
  color: var(--color-accent-blue);
}

/* Whatever the reader still has to answer: a form field, or a whole region like
   the month grid or the slots panel. The ring is a box-shadow rather than a
   border so nothing reflows when it appears — .input-field has border: 0, and
   adding one would shift every field by two pixels. Two layers: a crisp edge
   plus a soft outer glow, so it reads as the field lighting up rather than as a
   hairline outline. Colour is the palette's Status > Bad, so it follows the
   global set instead of being a fixed red. */
.invalid {
  box-shadow:
    0 0 0 var(--sr-alert-ring)
      color-mix(in srgb, var(--color-status-unavailable) var(--sr-alert-strength), transparent),
    0 0 calc(var(--sr-alert-ring) * 8) calc(var(--sr-alert-ring) * 1.5)
      color-mix(in srgb, var(--color-status-unavailable) calc(var(--sr-alert-strength) * 0.45), transparent);
  border-radius: var(--sr-rad-control);
  animation: alertPulse 1.6s ease-out 1;
}

.input-field.invalid {
  background: color-mix(in srgb, var(--color-status-unavailable) 7%, var(--color-bg) 50%);
}

/* One slow breath as it appears. Enough to catch the eye after a sweep, then it
   settles — a looping pulse would nag. */
@keyframes alertPulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-status-unavailable) var(--sr-alert-strength), transparent); }
}

@media (prefers-reduced-motion: reduce) {
  .invalid {
    animation: none;
  }
}

textarea.input-field {
  min-height: 48px;
  resize: none;
}

select.input-field {
  appearance: none;
  -webkit-appearance: none;
  background-color: color-mix(in srgb, var(--color-bg) 96%, transparent);
  background-image:
    linear-gradient(45deg, transparent 50%, var(--color-text-secondary) 50%),
    linear-gradient(135deg, var(--color-text-secondary) 50%, transparent 50%);
  background-position:
    calc(100% - 18px) 50%,
    calc(100% - 12px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  color: var(--color-text-primary);
}

select.input-field option {
  background: var(--color-bg);
  color: var(--color-text-primary);
}

select.input-field option:checked {
  background: var(--color-surface-solid);
  color: var(--color-text-primary);
}

.native-select-hidden {
  display: none;
}

/* --- SITE PRIVATE PREVIEW GATE --- */
.site-gate-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  /* The app's own background, straight from the agent's Colors & Identity >
     Background — the gate is the same room, not a different one. It used to be
     a radial gradient centred on --color-surface-solid, which read as near-white
     against the lavender page behind it. */
  background: var(--color-bg);
  z-index: var(--z-gate);
  display: flex;
  justify-content: center;
  align-items: center;
  opacity: 1;
  pointer-events: all;
  transition: opacity 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.site-gate-overlay.hidden {
  opacity: 0;
  pointer-events: none;
}

.site-gate-card {
  background: var(--sr-window-bg);
  border-radius: var(--sr-rad-window);
  backdrop-filter: blur(var(--sr-window-blur));
  -webkit-backdrop-filter: blur(var(--sr-window-blur));
  padding: var(--sr-window-pad);
  width: min(90%, 420px);
  box-shadow: var(--sr-window-shadow);
  transform: translateY(0);
  transition: transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.site-gate-overlay.hidden .site-gate-card {
  transform: translateY(-30px);
}

.site-gate-card.shake {
  animation: gateShake 0.3s ease;
}

@keyframes gateShake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-8px); }
  75% { transform: translateX(8px); }
}

.gate-logo-row {
  display: flex;
  justify-content: center;
  margin-bottom: 1.5rem;
}

/* The gate mark had no size rule at all, so it rendered at the SVG's intrinsic
   size and swallowed the card. Sized from the agent like every other mark. */
.gate-logo-row .logo-mini {
  width: auto;
  height: var(--sr-gatelogo);
}



/* --- PORTADA / SPLASH --- */
#viewPortada {
  padding-top: 0;
  padding-bottom: 0;
}

.portada-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  max-width: 480px;
  width: min(90vw, 480px);
  min-height: min(74vh, 620px);
  animation: none;
}

.portada-logo {
  width: calc(clamp(220px, 56vmin, 390px) * 0.7070707 * var(--sr-logo));
  height: calc(clamp(220px, 56vmin, 390px) * var(--sr-logo));
  display: block;
  margin-bottom: clamp(1.25rem, 4vh, 2.25rem);
  filter: drop-shadow(0 0 15px color-mix(in srgb, var(--color-text-primary) 5%, transparent));
  transition: var(--transition-smooth);
}

.portada-logo:hover {
  filter: drop-shadow(0 0 30px color-mix(in srgb, var(--color-accent-blue) 25%, transparent));
}

.portada-btn-container {
  opacity: 0;
  transform: translateY(15px);
  animation: textReveal 1.5s 3.5s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

@keyframes textReveal {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* --- LOGO MOTION: exact brand SVG layers, themed across Dark/Mid/Clear.
   !important is required here: the Inkscape source carries inline style
   attributes on every path. Line art + wordmark track the active theme's
   text color; the violet accent shapes (layer2/layer9) stay fixed brand
   violet regardless of theme, and ignore the source's mix-blend-mode:darken
   (which would nearly erase them against a dark ground). --- */
.siriah-logo {
  overflow: visible;
  shape-rendering: geometricPrecision;
}

.siriah-logo #layer11,
.siriah-logo #rect3 {
  display: none !important;
}

.siriah-logo #layer8 path,
.siriah-logo #layer3 path,
.siriah-logo #layer7 path {
  fill: none !important;
  stroke: color-mix(in srgb, var(--color-text-primary) 70%, transparent) !important;
  stroke-linecap: round !important;
  stroke-linejoin: round !important;
}

.siriah-logo #layer8 path,
.siriah-logo #layer7 path,
.siriah-logo #path29 {
  stroke-width: 0.58 !important;
}

.siriah-logo #layer3 #layer4 path {
  stroke-width: 0.24 !important;
  stroke: color-mix(in srgb, var(--color-text-secondary) 65%, transparent) !important;
}

.siriah-logo #layer2 circle {
  fill: #af8cff !important;
  fill-opacity: 0.5 !important;
  stroke: none !important;
  mix-blend-mode: normal !important;
}

.siriah-logo #layer9 path {
  fill: #9a6cff !important;
  fill-opacity: 0.45 !important;
  stroke: none !important;
  mix-blend-mode: normal !important;
}

.siriah-logo #layer6 circle {
  fill: color-mix(in srgb, var(--color-text-primary) 85%, transparent) !important;
  stroke: none !important;
}

.siriah-logo #layer1 text,
.siriah-logo #layer1 tspan {
  fill: var(--color-text-primary) !important;
  stroke: none !important;
}

.siriah-logo #layer1 text:first-of-type,
.siriah-logo #text82,
.siriah-logo #tspan82 {
  letter-spacing: 2.64583px !important;
}

.lg-bg-watermark {
  width: 96%;
  height: 96%;
  display: block;
  transform-origin: center;
}

body.preview-authorized .portada-wrapper {
  animation: brandBreath 4.8s cubic-bezier(0.42, 0, 0.16, 1) 3 both;
}

/* One-time entrance reveal — portada only. The payment ritual reuses the same
   logo but shows it fully drawn/static from the first frame (no repeated
   trace/fade over the ~14s payment wait — settled presence, not a show). */
body.preview-authorized .portada-logo:not(.logo-ritual) #layer8 path,
body.preview-authorized .portada-logo:not(.logo-ritual) #layer3 path,
body.preview-authorized .portada-logo:not(.logo-ritual) #layer7 path {
  stroke-dasharray: 120;
  stroke-dashoffset: 120;
  opacity: 0;
  animation: metatronTrace 4.8s cubic-bezier(0.34, 0.02, 0.12, 1) 0s 3 both;
}

body.preview-authorized .portada-logo:not(.logo-ritual) #layer2 circle,
body.preview-authorized .portada-logo:not(.logo-ritual) #layer6 circle,
body.preview-authorized .portada-logo:not(.logo-ritual) #layer9 path {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: metatronNodes 4.8s cubic-bezier(0.22, 1, 0.36, 1) 0s 3 both;
}

body.preview-authorized .portada-logo:not(.logo-ritual) #layer1 {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: wordmarkArrive 4.8s cubic-bezier(0.2, 0.8, 0.2, 1) 0s 3 both;
}

@keyframes brandBreath {
  0% { transform: scale(0.985); filter: drop-shadow(0 0 6px rgba(184, 207, 240, 0.06)); }
  28% { transform: scale(1.01); filter: drop-shadow(0 0 18px rgba(184, 207, 240, 0.16)); }
  58% { transform: scale(1); filter: drop-shadow(0 0 26px rgba(184, 207, 240, 0.22)); }
  100% { transform: scale(1); filter: drop-shadow(0 0 18px rgba(184, 207, 240, 0.14)); }
}

@keyframes metatronTrace {
  0% { opacity: 0; stroke-dashoffset: 120; }
  8% { opacity: 0.95; }
  34% { opacity: 1; stroke-dashoffset: 0; }
  100% { opacity: 1; stroke-dashoffset: 0; }
}

@keyframes metatronNodes {
  0%, 22% { opacity: 0; transform: scale(0.62); }
  36% { opacity: 0.86; transform: scale(1.18); }
  48%, 100% { opacity: 0.78; transform: scale(1); }
}

@keyframes wordmarkArrive {
  0%, 56% { opacity: 0; transform: translateY(4px); filter: blur(2px); }
  72% { opacity: 1; transform: translateY(0); filter: blur(0); }
  100% { opacity: 1; transform: translateY(0); filter: blur(0); }
}

/* --- REDUCED MOTION: freeze everything, show final state --- */
@media (prefers-reduced-motion: reduce) {

  /* changeLanguage() also skips the fade entirely here, but the swap must not
     depend on a transition that will never fire. */
  .app-container {
    transition: none !important;
  }

  .portada-wrapper,
  .portada-logo line,
  .portada-logo circle,
  .portada-logo g,
  .portada-logo text,
  .portada-btn-container,
  .logo-mini g,
  .logo-mini circle {
    animation: none !important;
  }

  .portada-logo line {
    stroke-dashoffset: 0;
  }

  .portada-logo circle,
  .portada-logo text,
  .portada-btn-container {
    opacity: 1;
    transform: none;
  }

  .nav-link,
  .calendar-day-num,
  .slot-btn {
    transition-duration: 0.01ms !important;
  }
}

/* --- PAYMENT RITUAL: same source logo, same size/glow/reveal as the portada --- */
.logo-ritual {
  margin: 0 auto 1.25rem;
}

/* --- RESERVATION SIGIL: deterministic seal derived from the booking id --- */
.sigil {
  color: var(--color-text-secondary);
  display: block;
}

.sigil .sigil-orbit {
  fill: none;
  stroke: currentColor;
  stroke-width: 0.9;
  opacity: 0.55;
}

.sigil line {
  stroke: currentColor;
  stroke-width: 0.45;
  opacity: 0.22;
}

.sigil line.on {
  stroke: var(--color-accent-blue);
  stroke-width: 1.2;
  opacity: 0.95;
}

.sigil circle.node {
  fill: none;
  stroke: currentColor;
  stroke-width: 0.6;
  opacity: 0.5;
}

.sigil circle.node.on {
  stroke: var(--color-accent-blue);
  opacity: 1;
}

.admin-table .sigil {
  display: inline-block;
  vertical-align: middle;
  margin-right: 8px;
}

.dialog-ornament {
  display: flex;
  justify-content: center;
}

.dialog-ornament:not(:empty) {
  margin: 0.5rem 0 1rem;
}

.ornament-duo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
}

/* --- ENERGY CHART: the private note as a configurable constellation --- */
.energy-chart-holder {
  display: flex;
  justify-content: center;
}

.energy-chart {
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  color: var(--color-text-secondary);
  display: block;
}

/* Booking view: scale the chart up for prominence (viewBox keeps drag math exact) */
.energy-chart-holder .energy-chart {
  width: min(100%, clamp(260px, 34vh, 360px));
  height: auto;
}

@media (orientation: portrait) {
  .energy-chart-holder .energy-chart {
    width: min(78vw, 340px);
  }
}

.energy-chart .ec-orbit {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  opacity: 0.35;
}

.energy-chart .ec-guide {
  fill: none;
  stroke: currentColor;
  stroke-width: 0.7;
  opacity: 0.12;
}

.energy-chart .ec-axis {
  stroke: currentColor;
  stroke-width: 0.7;
  opacity: 0.18;
}

.energy-chart .ec-field {
  fill: hsl(var(--accent-h) var(--accent-s) var(--accent-l) / 0.08);
  stroke: hsl(var(--accent-h) var(--accent-s) var(--accent-l) / 0.55);
  stroke-width: 1.1;
  pointer-events: none;
}

.energy-chart .ec-rel {
  stroke-width: 1.2;
  opacity: 0.9;
}

.energy-chart .ec-rel.vinculo {
  stroke: var(--color-accent-blue);
}

.energy-chart .ec-rel.tension {
  stroke: var(--color-status-reserved);
  stroke-dasharray: 4 3;
}

.energy-chart .ec-node {
  fill: var(--color-surface-solid);
  stroke: rgba(226, 234, 246, 0.45);
  stroke-width: 1.5;
  pointer-events: none;
  transition: fill 180ms ease;
}

.energy-chart .ec-field,
.energy-chart .ec-value {
  transition: fill 180ms ease, stroke 180ms ease;
}

.energy-chart .ec-node.armed {
  stroke: var(--color-text-primary);
  stroke-width: 2.2;
  filter: drop-shadow(0 0 4px var(--color-accent-blue-glow));
}

.energy-chart .ec-hit {
  fill: transparent;
  cursor: grab;
}

.energy-chart .ec-hit:active {
  cursor: grabbing;
}

.energy-chart .ec-label {
  fill: var(--color-text-secondary);
  font-size: 9px;
  letter-spacing: 0.6px;
  font-family: var(--font-primary);
}

.energy-chart .ec-value {
  fill: var(--color-text-primary);
  font-size: 11px;
  font-weight: 600;
  font-family: var(--font-primary);
}

.energy-chart-hint {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  line-height: 1.6;
  text-align: center;
  letter-spacing: 0.3px;
  margin-top: 2px;
}

.energy-chart-hint .hint-vinculo {
  color: var(--color-accent-blue);
}

.energy-chart-hint .hint-tension {
  color: var(--color-status-reserved);
}

/* --- INICIO SECTION --- */
.philosophy-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sr-gap);
  margin-top: 1rem;
}

@media (max-width: 500px) {
  .philosophy-grid {
    grid-template-columns: 1fr;
  }
}

.philosophy-card {
  padding: var(--sr-cell-pad);
  background: var(--sr-cell-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--sr-rad-cell);
  box-shadow: var(--sr-cell-shadow);
  transition: var(--transition-fast);
}

.philosophy-card:hover {
  background: color-mix(in srgb, var(--color-text-primary) 4%, transparent);
}

.philosophy-card h3 {
  margin-bottom: 0.8vh;
  color: var(--color-accent-blue);
}

.philosophy-card p {
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  line-height: 1.5;
}

/* --- SESIONES: AUTH --- */
.auth-panel {
  max-width: 400px;
  width: 90%;
  margin: auto;
  padding: calc(var(--sr-window-pad) * 1.2);
  background: var(--sr-window-bg);
  border-radius: var(--sr-rad-window);
  backdrop-filter: blur(var(--sr-window-blur));
  -webkit-backdrop-filter: blur(var(--sr-window-blur));
  box-shadow: var(--sr-window-shadow);
  display: flex;
  flex-direction: column;
}

.auth-header {
  text-align: center;
  margin-bottom: 2rem;
}


.auth-actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 1.5rem;
}

/* The two labels are long in German ("Zugang erstellen" / "Passwort
   wiederherstellen"), so they need a real gap and room to wrap rather than
   running into each other. Each takes half the row and wraps inside it. */
.auth-links {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sr-gap);
  margin-top: 1rem;
}

.auth-links .auth-link:last-child {
  text-align: right;
}

/* Tertiary actions beside the primary submit. No underline and no rule of any
   kind — they carry the same treatment as the field labels above them and
   answer on hover with colour alone. Type comes from the shared rule with
   .form-label; only the colour is theirs. */
.auth-link {
  cursor: pointer;
  background: none;
  text-align: left;
  transition: var(--transition-fast);
}

/* They already sit in the accent, so hover answers by deepening to the primary
   text colour rather than changing hue. */
.auth-link:hover {
  color: var(--color-text-primary);
}

/* --- SESIONES: SCHEDULER --- */
.scheduler-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  grid-template-rows: minmax(0, 1fr) auto;
  grid-template-areas:
    "details calendar"
    "details footer";
  height: 100%;
}

.details-section {
  grid-area: details;
}

.calendar-section {
  grid-area: calendar;
}

.booking-footer {
  grid-area: footer;
}

/* No size of its own: it is a .section-panel, so Window w/h governs it like
   every other window. It used to carry min(96vw, 1140px) / min(84vh, 700px)
   here, plus a different formula per orientation below — three sizing rules for
   the one panel that then never matched the other tabs. */

@media (max-width: 950px) {
  .scheduler-grid {
    grid-template-columns: minmax(0, 1.08fr) minmax(280px, 0.92fr);
    overflow: hidden;
  }

  .calendar-section,
  .details-section {
    height: 100%;
  }
}

.calendar-section {
  padding: calc(var(--sr-pad) * 0.72);
  display: flex;
  flex-direction: column;
  height: 100%;
  justify-content: space-between;
  min-width: 0;
}

.calendar-header {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: clamp(0.6rem, 2vw, 1.25rem);
  margin-bottom: clamp(0.65rem, 1.8vh, 1rem);
}


.calendar-nav-btn {
  background: none;
  color: var(--color-text-secondary);
  width: 34px;
  height: 34px;
  border-radius: var(--sr-rad-small);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.65rem;
  transition: var(--transition-fast);
}

.calendar-nav-btn:hover {
  background: color-mix(in srgb, var(--color-text-primary) 8%, transparent);
  color: var(--color-text-primary);
}

/* Calendar Grid */
.calendar-widget {
  display: flex;
  flex-direction: column;
  gap: calc(var(--sr-gap) * 0.5);
  flex: 1;
  margin-bottom: clamp(0.5rem, 1.5vh, 1rem);
  min-height: 0;
}

.calendar-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  text-align: center;
  font-weight: 600;
  font-size: 0.7rem;
  color: var(--color-accent-blue);
  text-transform: uppercase;
  letter-spacing: 1px;
  padding-bottom: clamp(4px, 0.8vh, 6px);
}

.calendar-days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: calc(var(--sr-gap) * 0.5);
  flex: 1;
  min-height: 0;
}

.calendar-day {
  background: color-mix(in srgb, var(--color-text-primary) 4.5%, transparent);
  border-radius: var(--sr-rad-small);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  padding: clamp(4px, 0.8vh, 7px) 4px 4px;
  cursor: pointer;
  transition: var(--transition-fast);
  position: relative;
  min-height: clamp(36px, 8.8vh, 58px);
}

.calendar-day:hover {
  background: color-mix(in srgb, var(--color-text-primary) 8%, transparent);
}

.calendar-day-num {
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--color-text-secondary);
  display: inline-block;
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), color 0.25s ease, font-weight 0.2s ease;
}

/* Day State Styles */
.calendar-day.empty {
  background: transparent;
  pointer-events: none;
}

.calendar-day.state-available {
  background: color-mix(in srgb, var(--color-status-available) 8%, transparent);
}

.calendar-day.state-available:hover {
  background: color-mix(in srgb, var(--color-status-available) 20%, transparent);
}

.calendar-day.state-reserved {
  background: color-mix(in srgb, var(--color-status-reserved) 8%, transparent);
  cursor: not-allowed;
  opacity: 0.78;
}

.calendar-day.state-unavailable {
  background: color-mix(in srgb, var(--color-status-unavailable) 7.5%, transparent);
  cursor: not-allowed;
  opacity: 0.72;
}

.calendar-day.state-next-open {
  background: color-mix(in srgb, var(--color-status-pending) 10%, transparent);
}

/* Selected always beats the state tint, including on hover */
.calendar-day.selected,
.calendar-day.state-available.selected,
.calendar-day.state-next-open.selected {
  background: color-mix(in srgb, var(--color-accent-blue) 45%, transparent);
  color: var(--color-text-primary);
}

.calendar-day.selected .calendar-day-num {
  color: var(--color-text-primary);
  font-weight: 700;
  transform: scale(var(--sr-sel-scale));
}

/* Slots & Details Section */
.details-section {
  padding: calc(var(--sr-pad) * 0.72);
  display: flex;
  flex-direction: column;
  height: 100%;
  justify-content: space-between;
  min-width: 0;
  position: relative;
}

.details-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 1rem;
}

#btnLogout {
  position: absolute;
  top: clamp(0.7rem, 1.7vw, 1rem);
  right: clamp(0.65rem, 1.8vw, 1rem);
  width: auto;
  min-width: 0;
  padding: 6px 9px;
  font-size: 0.56rem;
  line-height: 1.1;
  letter-spacing: 2px;
  opacity: 0.78;
}

#btnLogout:hover {
  opacity: 1;
}

/* Horario appears only once a date is picked */
.calendar-slots-panel {
  display: none;
  margin-top: clamp(0.8rem, 2vh, 1.2rem);
}

.calendar-slots-panel.visible {
  display: block;
}

.slots-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: calc(var(--sr-gap) * 0.5);
  margin-bottom: 1.25rem;
}

.calendar-section .slots-grid {
  margin: 0;
}

.slot-btn {
  background: color-mix(in srgb, var(--color-text-primary) 4%, transparent);
  color: var(--color-text-secondary);
  padding: 8px 4px;
  border-radius: var(--sr-rad-control);
  font-size: 0.76rem;
  cursor: pointer;
  text-align: center;
  transition: background 0.25s ease, color 0.25s ease, font-weight 0.2s ease,
    transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.slot-btn:hover {
  background: color-mix(in srgb, var(--color-text-primary) 6.5%, transparent);
}

.slot-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.slot-btn.selected,
.slot-btn.slot-btn.selected {
  background: color-mix(in srgb, var(--color-accent-blue) 45%, transparent);
  color: var(--color-text-primary);
  font-weight: 700;
  transform: scale(var(--sr-sel-scale));
}

.booking-options {
  margin-top: clamp(0.85rem, 2vh, 1.2rem);
  display: flex;
  flex-direction: column;
}

/* Landscape: the energy chart leads the left column */
@media (orientation: landscape) {
  .form-group-energy {
    order: -1;
  }
}

.booking-footer {
  position: sticky;
  bottom: 0;
  z-index: var(--z-sticky);
  padding: 0.85rem calc(var(--sr-pad) * 0.72) 0.85rem;
  background: var(--color-surface-solid);
}

.booking-cost-row {
  display: flex;
  justify-content: space-between;
  font-size: 0.85rem;
  margin-bottom: 12px;
  color: var(--color-text-secondary);
}

.booking-cost-value {
  font-weight: 600;
  color: var(--color-text-primary);
}

#btnProceedToPayment {
  min-height: 40px;
  padding: 10px 14px;
  font-size: 0.78rem;
}

/* --- FIELD PICKERS: custom popover replacements for native selects --- */
.field-picker {
  position: relative;
  width: 100%;
  min-width: 0;
  display: block;
}

.field-picker-trigger {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "kicker meta"
    "value meta";
  align-items: center;
  gap: 2px 12px;
  width: 100%;
  min-width: 0;
  min-height: 48px;
  padding: 8px 12px;
  border-radius: var(--sr-rad-control);
  background: var(--sr-dropdown-bg);
  color: var(--color-text-secondary);
  text-align: left;
}

.field-picker-kicker {
  grid-area: kicker;
  color: var(--color-accent-blue);
  font-size: 0.6rem;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  max-width: 100%;
}

/* Every picker reads as one control: the chosen value and the options it was
   chosen from are uppercase with tracking, like the tabs the category picker
   replaces in portrait. Each picker keeps its own size — a menu row wants more
   than a compact chip — but the treatment is shared. */
.field-picker-value,
.field-picker-option,
.field-picker-meta {
  text-transform: uppercase;
  letter-spacing: 1px;
}

.field-picker-value {
  grid-area: value;
  min-width: 0;
  white-space: normal;
  /* The chosen value, in the same accent as an active tab or nav item. */
  color: var(--sr-dropdown-chosen);
  font-size: 0.84rem;
  line-height: 1.25;
  max-width: 100%;
}

.field-picker-meta {
  grid-area: meta;
  color: var(--color-accent-blue);
  font-size: 0.72rem;
  white-space: nowrap;
  justify-self: end;
  max-width: 100%;
}

/* One single panel: options are plain rows, distinguished by color only */
.field-picker-popover {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  z-index: var(--z-popover);
  display: grid;
  gap: 0;
  padding: 8px 12px;
  border-radius: var(--sr-rad-window);
  background: var(--sr-dropdown-panel);
  backdrop-filter: blur(var(--sr-window-blur));
  -webkit-backdrop-filter: blur(var(--sr-window-blur));
  box-shadow: var(--sr-window-shadow);
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity 180ms ease, transform 180ms ease;
}

.field-picker.open .field-picker-popover {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.field-picker-option {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 0;
  padding: 7px 0;
  background: none;
  text-align: left;
  cursor: pointer;
  transition: var(--transition-fast);
}

/* One quiet colour for every row and every part of a row. The option markup
   carries <span>/<small>/<strong> for name, duration and price, which were
   picking up their own brighter colours and turning a list into a scatter of
   highlights. The list is something to read down. */
.field-picker-option,
.field-picker-option span,
.field-picker-option small,
.field-picker-option strong {
  color: var(--sr-dropdown-text);
}

.field-picker-option span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.field-picker-option small,
.field-picker-option strong {
  color: var(--color-text-secondary);
  font-size: 0.76rem;
  font-weight: 500;
}

.field-picker-option:hover,
.field-picker-option:hover span,
.field-picker-option:hover small,
.field-picker-option:hover strong {
  color: var(--color-text-primary);
}

/* The chosen option is already displayed on the trigger directly above, so
   repeating it in the list is the same name twice in one glance. Hidden while
   open; it returns to the list as soon as something else is chosen. */
.field-picker-option.active {
  display: none;
}

.consultation-choice strong {
  justify-self: end;
}

.modality-choice {
  display: block;
  line-height: 1.35;
}

.field-picker .modality-choice strong {
  justify-self: end;
  font-size: 0.7rem;
  font-weight: 400;
  white-space: nowrap;
}

/* --- ARTICLES / GALERIA DE PRODUCTOS --- */
/* Shared by Articulos and Cursos. Width/height are agent-managed percentages of
   the available area, so the list can be pushed to full-bleed. */
.articles-layout {
  display: flex;
  flex-direction: column;
  /* Window pad, like every other window's interior — not the generic --sr-pad. */
  padding: var(--sr-window-pad);
}

.articles-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: clamp(1.5rem, 3vh, 2.5rem);
}


.articles-scroll {
  flex: 1;
}

.cart-icon-btn {
  position: relative;
  background: color-mix(in srgb, var(--color-text-primary) 4.5%, transparent);
  color: var(--color-text-primary);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: var(--transition-fast);
}

.cart-icon-btn:hover {
  background: color-mix(in srgb, var(--color-text-primary) 8%, transparent);
}

#viewArticulos:not(.active) .cart-icon-btn {
  display: none;
}

#viewArticulos.active {
  transform: none;
  filter: none;
}

.cart-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  background: var(--color-accent-blue);
  color: white;
  font-size: 0.65rem;
  font-weight: 600;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Category Filter Bar */
.category-filter {
  display: flex;
  gap: 12px;
  margin-bottom: 1.5rem;
  overflow-x: auto;
  padding-bottom: 8px;
}

/* Category chooser as a dropdown instead of a scrolling row. Built in shop.js
   from the same .category-tab buttons, so the tabs stay the single source of
   truth for state. Landscape keeps the row; portrait swaps to the menu. */
.category-picker {
  display: none;
  margin-bottom: 1rem;
}

/* The category dropdown and the tab row are the same control in two
   orientations, so this picker also matches the tabs' size. */
.category-picker .field-picker-value,
.category-picker .category-option {
  font-size: 0.75rem;
}

@media (orientation: portrait) {
  .category-filter {
    display: none;
  }

  .category-picker {
    display: block;
  }
}

.category-filter::-webkit-scrollbar {
  display: none;
}

.category-tab {
  background: color-mix(in srgb, var(--color-text-primary) 4%, transparent);
  color: var(--color-text-secondary);
  min-height: 0;
  padding: 8px 16px;
  border-radius: var(--sr-rad-control);
  font-size: 0.75rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  cursor: pointer;
  transition: var(--transition-fast);
  white-space: nowrap;
}

.category-tab:hover {
  background: color-mix(in srgb, var(--color-text-primary) 6.5%, transparent);
}

/* The chosen tab answers exactly like the active nav item above it — same
   accent, so "where am I" reads the same everywhere. The tint alone was doing
   the work before, and against a white window it barely registered. */
.category-tab.active {
  background: color-mix(in srgb, var(--color-accent-blue) 18%, transparent);
  color: var(--sr-dropdown-chosen);
}

/* Grid of Articles */
.articles-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--sr-gap);
  flex: 1;
  /* Clearance so product-card shadows aren't shorn by the scroll edge */
  padding: 0 var(--sr-cell-room) var(--sr-cell-room);
}

.product-card {
  background: var(--sr-cell-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--sr-rad-cell);
  box-shadow: var(--sr-cell-shadow);
  padding: var(--sr-cell-pad);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  transition: var(--transition-smooth);
  position: relative;
  overflow: hidden;
  cursor: pointer;
}

/* Lift on hover: the same cell shadow the card already casts, doubled, so the
   agent's Cell Shadow controls the hover state too instead of it being a fixed
   pixel shadow that ignores them. */
.product-card:hover {
  transform: translateY(-0.3vh);
  box-shadow: var(--sr-cell-shadow), var(--sr-cell-shadow);
}

.product-category {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--color-accent-blue);
  margin-bottom: 6px;
}

.product-name {
  font-size: 0.95rem;
  font-weight: 400;
  margin-bottom: 8px;
  color: var(--color-text-primary);
}

.product-flag-out {
  color: var(--color-status-unavailable);
  font-size: 0.7rem;
  font-weight: 600;
}

.product-desc {
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  line-height: 1.5;
  margin-bottom: 1.25rem;
  flex-grow: 1;
}

.product-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 12px;
}

.courses-intro {
  max-width: 640px;
}

.course-audience {
  font-size: 0.72rem;
  color: var(--color-text-muted);
  font-style: italic;
  margin-top: -0.75rem;
  margin-bottom: 0.5rem;
}

.product-price {
  font-size: 1rem;
  font-weight: 500;
  color: var(--color-text-primary);
}

.product-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

.product-btn-buy {
  background: color-mix(in srgb, var(--color-accent-blue) 22%, transparent);
  color: var(--color-text-primary);
  font-weight: 600;
  font-size: 0.68rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  padding: 0 13px;
  height: 30px;
  min-height: 0;
  border-radius: var(--sr-rad-control);
  cursor: pointer;
  transition: var(--transition-fast);
}

.product-btn-buy:hover {
  background: color-mix(in srgb, var(--color-accent-blue) 30%, transparent);
}

.product-btn-buy:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

/* Stock state colors (product drawer + admin inventory) */
.stock-state.available {
  color: var(--color-status-available);
}

.stock-state.low {
  color: var(--color-status-reserved);
}

.stock-state.out {
  color: var(--color-status-unavailable);
}

/* Product Detail Drawer */
.product-drawer {
  position: fixed;
  top: 0;
  right: -420px;
  width: min(100vw, 420px);
  height: 100vh;
  background: var(--sr-window-bg);
  backdrop-filter: blur(var(--sr-window-blur));
  -webkit-backdrop-filter: blur(var(--sr-window-blur));
  z-index: var(--z-drawer);
  padding: var(--sr-window-pad);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  transition: right 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.product-drawer.open {
  right: 0;
  box-shadow: var(--sr-window-shadow);
}

.drawer-body {
  flex: 1;
  margin: 1.5rem 0;
}

.drawer-footer {
  border-top: 1px solid var(--color-border);
  padding-top: 1.5rem;
}

.drawer-close {
  align-self: flex-end;
  background: color-mix(in srgb, var(--color-text-primary) 5.5%, transparent);
  color: var(--color-text-secondary);
  font-size: 1.5rem;
  cursor: pointer;
  transition: var(--transition-fast);
}

.drawer-close:hover {
  color: var(--color-text-primary);
  background: color-mix(in srgb, var(--color-text-primary) 9%, transparent);
}

.drawer-product-title {
  font-size: 1.5rem;
  font-weight: 400;
  margin-top: 5px;
  margin-bottom: 1.5rem;
}

.drawer-product-desc {
  font-size: 0.85rem;
  line-height: 1.7;
  margin-bottom: 1.5rem;
}

.drawer-info-box {
  background: color-mix(in srgb, var(--color-text-primary) 1%, transparent);
  border: 1px solid var(--color-border);
  border-radius: var(--sr-rad-cell);
  padding: 1.25rem;
  font-size: 0.8rem;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.drawer-info-row {
  display: flex;
  justify-content: space-between;
}

.drawer-info-label {
  color: var(--color-text-secondary);
}

.drawer-info-price {
  color: var(--color-text-primary);
  font-size: 1.05rem;
}

.drawer-info-row .stock-state {
  font-weight: 500;
}

#btnDrawerAddToCart:disabled {
  opacity: 0.3;
}

/* Shopping Cart Drawer */
.cart-drawer {
  position: fixed;
  top: 0;
  right: -450px;
  width: min(100vw, 450px);
  height: 100vh;
  background: var(--sr-window-bg);
  backdrop-filter: blur(var(--sr-window-blur));
  -webkit-backdrop-filter: blur(var(--sr-window-blur));
  z-index: var(--z-drawer);
  padding: calc(var(--sr-window-pad) * 2);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  transition: right 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.cart-drawer.open {
  right: 0;
  box-shadow: var(--sr-window-shadow);
}

.cart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}


.cart-items {
  flex: 1;
  margin: 1.5rem 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.cart-empty {
  text-align: center;
  color: var(--color-text-secondary);
  font-size: 0.85rem;
  margin-top: 4rem;
}

.cart-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 12px;
  border-radius: var(--sr-rad-cell);
  background: color-mix(in srgb, var(--color-text-primary) 5%, transparent);
  border: 1px solid var(--color-border);
}

.cart-item-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.cart-item-name {
  font-size: 0.85rem;
  font-weight: 400;
}

.cart-item-price {
  font-size: 0.8rem;
  color: var(--color-text-secondary);
}

.cart-item-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  background: color-mix(in srgb, var(--color-text-primary) 4%, transparent);
  border-radius: var(--sr-rad-cell);
  padding: 2px;
}

.cart-item-qty {
  font-size: 0.8rem;
  min-width: 20px;
  text-align: center;
}

.cart-item-btn {
  background: transparent;
  color: var(--color-text-secondary);
  min-height: 0;
  width: 22px;
  height: 22px;
  border-radius: var(--sr-rad-control);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 0.75rem;
}

.cart-item-btn:hover {
  color: var(--color-text-primary);
  background: color-mix(in srgb, var(--color-text-primary) 10%, transparent);
}

.cart-total-bar {
  padding-top: 1.5rem;
  margin-bottom: 1rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 1rem;
  font-weight: 500;
}

.cart-total-value {
  font-weight: 600;
  color: var(--color-accent-blue);
}

/* --- CONTACTO SECTION --- */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: 100%;
}

@media (max-width: 850px) {
  .contact-grid {
    grid-template-columns: 1fr;
    overflow-y: auto;
  }
}

.contact-info-panel {
  padding: var(--sr-pad);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.contact-item {
  display: flex;
  align-items: center;
  gap: 15px;
  margin-bottom: 1.5rem;
}

.contact-icon {
  width: max(var(--sr-tap-min), 3vw);
  height: max(var(--sr-tap-min), 3vw);
  border-radius: 50%;
  background: color-mix(in srgb, var(--color-text-primary) 2%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-accent-blue);
  /* Drives the 1em glyph inside (see .icon svg) */
  font-size: 1.15rem;
  flex: 0 0 auto;
}

.contact-details h4 {
  color: var(--color-text-secondary);
}

.contact-details p {
  font-size: 0.9rem;
  color: var(--color-text-primary);
  margin-top: 2px;
}

.contact-form-panel {
  padding: var(--sr-pad);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.contact-submit-row {
  margin-top: 1.5rem;
}

/* --- PAYMENT MODAL (CELDA FLOTANTE) --- */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: var(--sr-scrim-bg);
  backdrop-filter: blur(var(--sr-scrim-blur));
  -webkit-backdrop-filter: blur(var(--sr-scrim-blur));
  z-index: var(--z-scrim);
  display: flex;
  justify-content: center;
  align-items: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
}

.modal-overlay.open {
  opacity: 1;
  pointer-events: all;
}

.modal-container {
  background: var(--sr-window-bg);
  border-radius: var(--sr-rad-window);
  width: min(90%, 550px);
  max-height: min(90vh, 700px);
  box-shadow: var(--sr-window-shadow);
  display: flex;
  flex-direction: column;
  transform: scale(0.95);
  transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
  overflow: hidden;
}

.modal-container.modal-compact {
  max-height: min(90vh, 580px);
  width: min(90%, 480px);
}

.modal-overlay.open .modal-container {
  transform: scale(1);
}

.modal-header {
  padding: 1rem 1.5rem 1.5rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
}


.modal-close {
  background: color-mix(in srgb, var(--color-text-primary) 5.5%, transparent);
  color: var(--color-text-secondary);
  font-size: 1.5rem;
  cursor: pointer;
}

.modal-close:hover {
  background: color-mix(in srgb, var(--color-text-primary) 9%, transparent);
}

.modal-body {
  padding: var(--sr-pad);
  flex: 1;
}

.modal-subtag {
  margin-bottom: 6px;
  display: block;
}

.modal-footer {
  padding: 1rem 1.5rem 1.25rem;
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}

/* Reservation summary: same visual language as the booking view */
.reservation-summary-box {
  background: transparent;
  border-radius: var(--sr-rad-cell);
  padding: 0;
  margin-bottom: 1.25rem;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.summary-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: color-mix(in srgb, var(--color-text-primary) 3.5%, transparent);
  border-radius: var(--sr-rad-cell);
  padding: 10px 14px;
}

.summary-span {
  grid-column: span 2;
}

.summary-label {
  font-size: 0.6rem;
  text-transform: uppercase;
  color: var(--color-accent-blue);
  letter-spacing: 2.4px;
}

.summary-value {
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--color-text-primary);
}

.summary-value.highlight {
  color: var(--color-accent-blue);
  font-weight: 600;
}

.summary-meta {
  font-size: 0.7rem;
  color: var(--color-accent-blue);
}

.summary-item.summary-chart {
  grid-column: span 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 12px 14px 14px;
}

.summary-item.summary-chart .summary-label {
  align-self: flex-start;
}

.payment-methods-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: calc(var(--sr-gap) * 0.5);
  margin-bottom: 1.25rem;
}

.payment-method-btn {
  background: color-mix(in srgb, var(--color-text-primary) 4%, transparent);
  color: var(--color-text-secondary);
  min-height: 0;
  padding: 10px 4px;
  border-radius: var(--sr-rad-control);
  font-size: 0.75rem;
  text-align: center;
  cursor: pointer;
  transition: var(--transition-fast);
}

.payment-method-btn:hover {
  background: color-mix(in srgb, var(--color-text-primary) 6.5%, transparent);
}

.payment-method-btn.selected {
  background: color-mix(in srgb, var(--color-accent-blue) 18%, transparent);
  color: var(--color-text-primary);
  font-weight: 500;
}

.payment-details-form {
  padding-top: 1rem;
}

.card-meta-grid {
  display: grid;
  grid-template-columns: 1.2fr 0.8fr;
  gap: 10px;
}

.qr-code-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: color-mix(in srgb, var(--color-text-primary) 1%, transparent);
  border: 1px dashed var(--color-border);
  border-radius: var(--sr-rad-cell);
  gap: 12px;
}

.qr-code-placeholder .form-group {
  width: 100%;
}

.qr-code-image {
  width: 140px;
  height: 140px;
  background: white;
  padding: 8px;
  border-radius: var(--sr-rad-small);
}

.qr-note {
  font-size: 0.8rem;
  text-align: center;
  color: var(--color-text-secondary);
}

.qr-note strong {
  color: var(--color-text-primary);
  font-size: 0.95rem;
}

.bank-details-box {
  background: color-mix(in srgb, var(--color-text-primary) 1%, transparent);
  border: 1px solid var(--color-border);
  border-radius: var(--sr-rad-cell);
  padding: 1.25rem;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
}

.bank-line-title {
  margin-bottom: 8px;
}

.bank-account-lines {
  color: var(--color-text-primary);
  font-family: monospace;
}

.bank-holder {
  margin-top: 12px;
  margin-bottom: 8px;
}

.bank-note {
  font-size: 0.75rem;
  border-top: 1px solid var(--color-border);
  padding-top: 10px;
  margin-top: 10px;
  color: var(--color-accent-blue);
}

.bank-field {
  margin-top: 1rem;
  width: 100%;
}

.bank-field-tight {
  margin-top: 0.5rem;
}

/* --- SIMULATED PAYMENT PROCESSING --- */
.payment-loader {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2.5rem;
  text-align: center;
  gap: 1.5rem;
}

.payment-status-title {
  font-weight: 400;
  font-size: 1.1rem;
  color: var(--color-text-primary);
}

.payment-status-sub {
  color: var(--color-text-secondary);
  font-size: 0.8rem;
  line-height: 1.5;
  max-width: 320px;
  margin: 0 auto;
}

.payment-success-title {
  font-weight: 400;
  font-size: 1.25rem;
  color: var(--color-status-available);
  margin-top: 10px;
}

.payment-success-desc {
  color: var(--color-text-secondary);
  font-size: 0.85rem;
  line-height: 1.6;
  max-width: 340px;
  margin: 0 auto;
}

.tx-code {
  color: var(--color-accent-blue);
  font-family: monospace;
  font-weight: 600;
}

.payment-finish-btn {
  margin-top: 1.5rem;
  padding: 10px 30px;
}

.success-checkmark {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--color-status-available) 12%, transparent);
  border: 2px solid var(--color-status-available);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-status-available);
  font-size: 2rem;
  font-weight: bold;
  animation: scaleUp 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

@keyframes scaleUp {
  0% {
    transform: scale(0.7);
    opacity: 0;
  }

  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.payment-progress-bar {
  width: 100%;
  height: 4px;
  background: color-mix(in srgb, var(--color-text-primary) 5%, transparent);
  border-radius: var(--sr-rad-small);
  overflow: hidden;
  margin-top: 10px;
}

.payment-progress-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--color-accent-blue) 0%, var(--color-accent-violet) 100%);
  animation: fillProgress 3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes fillProgress {
  to {
    width: 100%;
  }
}

/* --- ADMIN PANEL --- */
.admin-panel {
  width: min(95%, 1200px);
  height: min(85vh, 750px);
}

.admin-layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  height: 100%;
}

.admin-sidebar {
  background: color-mix(in srgb, var(--color-bg) 60%, transparent);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.admin-brand-tag {
  padding-left: 12px;
  margin-bottom: 12px;
}

.admin-sidebar-btn {
  background: none;
  color: var(--color-text-secondary);
  padding: 12px 16px;
  text-align: left;
  border-radius: var(--sr-rad-control);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  cursor: pointer;
  transition: var(--transition-fast);
  width: 100%;
}

.admin-sidebar-btn:hover {
  background: color-mix(in srgb, var(--color-text-primary) 3%, transparent);
  color: var(--color-text-primary);
}

.admin-sidebar-btn.active {
  background: color-mix(in srgb, var(--color-accent-blue) 18%, transparent);
  color: var(--color-text-primary);
}

@media (max-width: 850px) {
  .admin-layout {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr;
  }

  .admin-sidebar {
    flex-direction: row;
    overflow-x: auto;
    padding: 10px;
  }

  .admin-sidebar-btn {
    width: auto;
    white-space: nowrap;
    padding: 8px 12px;
  }
}

.admin-viewport {
  padding: var(--sr-pad);
  height: 100%;
  overflow-y: auto;
}

.admin-tab-view {
  display: none;
}

.admin-tab-view.active {
  display: block;
}

.admin-card {
  background: var(--sr-cell-bg);
  border-radius: var(--sr-rad-cell);
  box-shadow: var(--sr-cell-shadow);
  padding: var(--sr-cell-pad);
  margin-bottom: 1.5rem;
}

.admin-card-title {
  margin-bottom: 1rem;
  /* The admin console tints its card headings with the accent to separate
     tooling chrome from customer-facing content. */
  color: var(--color-accent-blue);
}

.admin-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1.5rem;
}

.admin-card-header .admin-card-title {
  margin-bottom: 0;
}

.admin-note {
  font-size: 0.8rem;
  margin-bottom: 1.5rem;
}

.admin-availability-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
}

.admin-btn-row {
  display: flex;
  gap: 10px;
  margin-top: 1rem;
}

.admin-btn-row .btn {
  flex: 1;
}

.admin-add-slot-btn {
  margin-top: 1rem;
}

/* Admin Tables / Lists */
.admin-table-container {
  width: 100%;
  overflow-x: auto;
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
  font-size: 0.8rem;
}

.admin-table th {
  padding: 10px;
  color: var(--color-text-secondary);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.admin-table td {
  padding: 12px 10px;
  color: var(--color-text-primary);
}

.table-subtext {
  color: var(--color-text-secondary);
  font-size: 0.75rem;
}

.table-mono {
  font-family: monospace;
  color: var(--color-accent-blue);
}

.table-empty-cell {
  text-align: center;
  color: var(--color-text-secondary);
}

.table-message-text {
  font-size: 0.75rem;
  color: var(--color-text-secondary);
  max-width: 400px;
  white-space: normal;
  word-break: break-word;
}

.table-verified-note {
  color: var(--color-text-secondary);
  font-size: 0.75rem;
}

.admin-badge {
  display: inline-block;
  padding: 3px 8px;
  /* A pill, not a rounded box: the radius must always exceed half the height,
     so it belongs with the deliberate circles rather than the corner scale. */
  border-radius: 50vw;
  font-size: 0.7rem;
  text-transform: uppercase;
  font-weight: 500;
}

.admin-badge.status-pending {
  background: color-mix(in srgb, var(--color-status-pending) 15%, transparent);
  color: var(--color-status-pending);
}

.admin-badge.status-confirmed {
  background: color-mix(in srgb, var(--color-status-available) 15%, transparent);
  color: var(--color-status-available);
}

.admin-badge.status-completed {
  background: color-mix(in srgb, var(--color-accent-blue) 15%, transparent);
  color: var(--color-accent-blue);
}

.admin-badge.status-cancelled {
  background: color-mix(in srgb, var(--color-status-unavailable) 15%, transparent);
  color: var(--color-status-unavailable);
}

.admin-actions-cell {
  display: flex;
  gap: 6px;
}

.admin-action-btn-small {
  padding: 4px 8px;
  font-size: 0.7rem;
  border-radius: var(--sr-rad-small);
}

/* Float admin back button */
.admin-exit-btn {
  position: absolute;
  top: 15px;
  right: 15px;
  z-index: var(--z-over-navbar);
}

/* --- TOAST NOTIFICATIONS --- */
.toast-container {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: 10px;
  pointer-events: none;
}

.toast {
  background: var(--sr-window-bg);
  backdrop-filter: blur(var(--sr-window-blur));
  -webkit-backdrop-filter: blur(var(--sr-window-blur));
  color: var(--color-text-primary);
  padding: 12px 20px 12px 16px;
  border-radius: var(--sr-rad-cell);
  border-left: 3px solid var(--color-border-base);
  box-shadow: var(--sr-window-shadow);
  font-size: 0.8rem;
  pointer-events: all;
  display: flex;
  align-items: center;
  gap: 10px;
  transform: translateY(50px);
  opacity: 0;
  transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), opacity 0.4s ease;
}

.toast.show {
  transform: translateY(0);
  opacity: 1;
}

/* Semantic tints — "warn" is the gentle nudge tone (e.g. "pick a date first"),
   distinct from "error" (something actually went wrong). */
.toast.warn {
  background: color-mix(in srgb, var(--color-status-reserved) 16%, var(--sr-window-color));
  border-left-color: var(--color-status-reserved);
}

.toast.error {
  background: color-mix(in srgb, var(--color-status-unavailable) 16%, var(--sr-window-color));
  border-left-color: var(--color-status-unavailable);
}

.toast.success {
  background: color-mix(in srgb, var(--color-status-available) 16%, var(--sr-window-color));
  border-left-color: var(--color-status-available);
}

.toast.info {
  background: color-mix(in srgb, var(--color-accent-blue) 16%, var(--sr-window-color));
  border-left-color: var(--color-accent-blue);
}

/* --- DIALOGS & OVERLAYS --- */
.dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: var(--sr-scrim-bg);
  backdrop-filter: blur(var(--sr-scrim-blur));
  -webkit-backdrop-filter: blur(var(--sr-scrim-blur));
  z-index: var(--z-scrim);
  display: flex;
  justify-content: center;
  align-items: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

.dialog-overlay.open {
  opacity: 1;
  pointer-events: all;
}

.dialog-box {
  background: var(--sr-window-bg);
  border-radius: var(--sr-rad-window);
  padding: calc(var(--sr-window-pad) * 1.6);
  width: min(90%, 400px);
  text-align: center;
  box-shadow: var(--sr-window-shadow);
  transform: scale(0.95);
  transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.dialog-overlay.open .dialog-box {
  transform: scale(1);
}

.dialog-title {
  margin-bottom: 1vh;
}

.dialog-message {
  font-size: 0.85rem;
  color: var(--color-text-secondary);
  line-height: 1.5;
  margin-bottom: 1.5rem;
}

.dialog-buttons {
  display: flex;
  gap: 10px;
  justify-content: center;
}

/* ============================================================
   RESPONSIVE — placed last so its ties win over component rules.
   Order matters: portrait-phone < portrait < phone (max 700px).
   ============================================================ */

/* Portrait phones */
@media (orientation: portrait) and (max-width: 700px) {
  /* .nav-brand's own gap already resolves via --sr-navgap (portrait media query
     at :root, width-independent) — no separate override needed here. */

  /* SIRIAH DAM stays visible on phones. It is capped rather than hidden: the bar
     has to hold the brand plus four icon+label items, and an uncapped wordmark
     (3.4vw x 2.2 = ~29px tall, ~88px wide) left no room and clipped the last item.
     The cap only bites on narrow screens; landscape keeps the full tuned scale. */
  /* Caps are proportional and deliberately sit ABOVE the default scales, so the
     agent's Hexagon/Wordmark values stay authoritative here. Absolute caps (26px /
     16px) were below the defaults and silently swallowed every change. */
  .nav-brand .siriah-wordmark {
    height: min(calc(3.4vw * var(--sr-navword, 1)), 9vw);
  }

  .nav-brand .logo-mini {
    width: min(calc(5.2vw * var(--sr-navhex, 1)), 11vw);
    height: min(calc(7.3vw * var(--sr-navhex, 1)), 15.5vw);
  }

  .nav-brand {
    flex: 0 1 auto;
    min-width: 0;
  }

  .nav-links {
    flex: 0 1 auto;
    justify-content: flex-end;
    min-width: 0;
  }

  .nav-links {
    gap: 1.2vw;
  }

  /* Same stacked icon-over-label structure as landscape; the label is tightened
     and capped so four items fit a phone's width regardless of the text scale. */
  .nav-link {
    font-size: min(calc(0.5rem * var(--sr-menutext, 1)), 9.5px);
    letter-spacing: 0;
    padding: 1vw 0.6vw;
    min-height: var(--sr-tap-min);
  }

  .lang-switcher-trigger {
    padding: 1vw 1.6vw;
    font-size: 0.52rem;
  }

  #viewPortada {
    align-items: center;
    padding: 0 2.6vw;
  }

  .portada-wrapper {
    min-height: 100svh;
    justify-content: center;
    padding: 4svh 0;
  }


  .calendar-nav-btn {
    width: max(var(--sr-tap-min), 8vw);
    height: max(var(--sr-tap-min), 8vw);
  }

  .calendar-widget {
    margin-bottom: 1.2vw;
  }

  .calendar-weekdays {
    letter-spacing: 0.4px;
  }

  .form-group {
    gap: 1vw;
  }

  .input-field {
    padding: 2.6vw 3vw;
    font-size: 0.84rem;
    min-height: var(--sr-tap-min);
  }

  .slots-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* Portrait (any width): panels become full-bleed documents */
@media (orientation: portrait) {
  /* No gutter on any side. The landscape rule reserves --sr-window-room so a
     floating panel's shadow is not sheared off, but portrait panels set
     box-shadow: none below — so that reservation was protecting a shadow that
     does not exist, and it was the band of background that Window w/h: 100%
     could never cover, at the sides and along the bottom. Each panel's own
     Window pad supplies the breathing room instead. */
  .view-section:not(#viewPortada) {
    padding-left: 0;
    padding-right: 0;
    padding-bottom: 0;
  }

  .section-panel,
  .articles-layout,
  .admin-panel {
    width: var(--sr-window-w);
    height: var(--sr-window-h);
    max-height: none;
    border-radius: 0;
    box-shadow: none;
  }

  /* Bounded (not auto) so the payment footer can be pinned in view from the
     start, instead of sitting at the bottom of a long stacked flow that
     required scrolling past the details/calendar content to ever see it. */
  /* Width, height, radius and shadow all come from the shared portrait rule
     for .section-panel above — this only needs to stop being scrollable. */
  #schedulerContainer {
    max-height: none;
  }

  .scheduler-grid {
    display: flex;
    flex-direction: column;
    height: 100%;
    gap: 0;
  }

  .details-section {
    height: auto;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
  }

  .calendar-section {
    height: auto;
    flex: 0 0 auto;
  }

  .booking-footer {
    flex: 0 0 auto;
    position: static;
  }

  .contact-grid,
  .admin-layout {
    height: auto;
  }

  .panel-content {
    height: auto;
    min-height: 0;
    overflow: visible;
  }

  .section-title {
    margin-bottom: 1rem;
  }

  .section-title-tag {
    margin-bottom: 0.9vh;
  }

  .philosophy-grid {
    margin-top: 0.75rem;
  }

  .philosophy-card p,
  .product-desc,
  .section-desc {
    line-height: 1.55;
  }

  .articles-layout {
    height: var(--sr-window-h);
    min-height: 0;
    overflow: visible;
  }

  .articles-header {
    margin-bottom: 1rem;
  }

  #viewArticulos .articles-header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--sr-gap);
  }

  /* One column, but keep the base rule's side clearance — zeroing padding-right
     here is what was shearing the product-card shadows against the scroll edge. */
  .articles-grid {
    grid-template-columns: 1fr;
  }

  .product-card {
    min-height: 0;
  }

  .contact-item {
    margin-bottom: 1rem;
  }

  .modal-overlay {
    align-items: stretch;
    padding: var(--sr-pad);
  }

  .modal-container,
  .modal-container.modal-compact {
    width: 100%;
    max-height: calc(100svh - (var(--sr-pad) * 2));
  }

  /* Cart trigger detaches into a fixed floating control, sitting a window-relative
     step below the nav bar rather than at a fixed 66px that drifts per device.
     Being fixed takes it out of the flow, so nothing below knows it is there —
     the header and the category menu reserve its lane explicitly, or it lands
     on top of them. */
  #viewArticulos .articles-header {
    padding-right: calc(var(--sr-cart-size) + var(--sr-window-pad));
  }

  /* Margin, not padding: the open list is absolutely positioned against this
     element's padding box, so padding would leave the menu wider than the
     trigger it belongs to. Margin shrinks the box itself and both follow —
     but only once width: 100% from .field-picker stops pinning it open. */
  #viewArticulos .category-picker {
    width: auto;
    margin-right: calc(var(--sr-cart-size) + var(--sr-window-pad));
  }

  #viewArticulos .cart-icon-btn {
    position: fixed;
    top: calc(var(--sr-nav) + var(--sr-pad));
    right: var(--sr-pad);
    z-index: var(--z-floating);
    width: var(--sr-cart-size);
    height: var(--sr-cart-size);
    min-width: var(--sr-tap-min);
    border-radius: 50%;
    background: var(--sr-dropdown-bg);
    color: var(--color-text-secondary);
    transform: none;
    box-shadow: none;
    display: flex;
  }

  #viewArticulos:not(.active) .cart-icon-btn {
    display: none;
  }

  #viewArticulos .cart-icon-btn svg {
    width: 5.2vw;
    height: 5.2vw;
    min-width: 18px;
    min-height: 18px;
  }

  #viewArticulos .cart-badge {
    top: -2px;
    right: -2px;
    width: max(16px, 4.6vw);
    height: max(16px, 4.6vw);
    font-size: 0.65rem;
    background: var(--color-accent-blue);
    color: #fff;
  }

  .calendar-slots-panel {
    margin-top: 1.8vw;
  }

  /* The logout control is in normal flow here, so no reserved gutter is needed */
  .details-toolbar {
    margin-bottom: 2.2vw;
  }

  .consultation-choice {
    grid-template-columns: minmax(0, 1fr) auto auto;
    gap: 2vw;
  }

  .consultation-choice span {
    white-space: nowrap;
  }
}

/* Phones (portrait or landscape) */
@media (max-width: 700px) {
  body,
  .btn,
  .input-field,
  .slot-btn,
  .consultation-choice,
  .modality-choice,
  .product-card {
    font-weight: 300;
  }

  /* Titles are excluded here: their weight is the agent's Titles > Weight
     control, and re-declaring it per breakpoint is what let the nine title
     rules drift apart in the first place. */
  .nav-brand,
  .product-name,
  .product-price,
  .booking-cost-value,
  .consultation-choice strong {
    font-weight: 400;
  }

  /* .section-title-tag and .form-label are excluded: their type is the agent's
     Titles > Label role, which already resolves per orientation. Re-declaring
     it here is what made a label and the auth links beside it disagree. */
  .product-category {
    font-size: 0.66rem;
    letter-spacing: 2.5px;
    font-weight: 500;
  }

  /* No side gutter: this breakpoint overlaps portrait, where the panel is a
     full-bleed document with no shadow to reserve room for. Re-adding it here
     is what kept Window w: 100% from reaching the edge. */
  .view-section:not(#viewPortada) {
    padding-left: 0;
    padding-right: 0;
  }

  .auth-panel {
    border-radius: var(--sr-rad-window);
  }

  .calendar-header {
    margin-bottom: 0.25rem;
  }


  .calendar-weekdays {
    font-size: 0.52rem;
    padding-bottom: 2px;
    margin-bottom: 3px;
  }

  .calendar-day {
    /* A calendar cell is 1/7th of the grid, so its height tracks window width */
    min-height: max(26px, 7vw);
    padding: 0.5vw;
    border-radius: var(--sr-rad-small);
  }

  .calendar-day-num {
    font-size: 0.72rem;
  }

  .calendar-slots-panel {
    margin-top: 0.45rem;
  }

  .calendar-section .slots-grid {
    gap: 1.3vw;
  }

  .slot-btn {
    padding: 1.8vw 0.8vw;
    font-size: 0.72rem;
    border-radius: var(--sr-rad-control);
    min-height: max(32px, 9vw);
  }

  .details-toolbar {
    margin-bottom: 0.55rem;
    padding-right: 0;
  }

  .details-section .section-title-tag {
    display: none;
  }

  .details-section label[for="consultationType"],
  .details-section label[for="consultationModality"] {
    display: none;
  }

  /* On phones the control sits in normal flow inside .details-toolbar, which is
     already flex/flex-end — so it right-aligns itself and reserves its own row.
     Both `fixed` and `absolute` failed here: a transformed ancestor redirects
     fixed-position `top`, and absolute took the button out of flow, collapsing the
     toolbar so the button landed on the booking rows. */
  #btnLogout {
    position: static;
    padding: 1.3vw 2vw;
    font-size: 0.5rem;
    letter-spacing: 1.6px;
  }

  .booking-options {
    margin-top: 0.45rem;
  }

  .field-picker-trigger {
    min-height: var(--sr-tap-min);
    padding: 1.8vw 2.6vw;
  }

  .field-picker-value {
    font-size: 0.78rem;
  }

  .field-picker-meta {
    font-size: 0.68rem;
  }

  .modality-picker .field-picker-meta {
    align-self: center;
  }

  .field-picker-popover {
    gap: 0;
  }

  .field-picker-option {
    padding: 1.6vw 0;
    font-size: 0.72rem;
    min-height: max(32px, 9vw);
    display: flex;
    align-items: center;
  }

  .consultation-choice {
    grid-template-columns: minmax(0, 1fr) 11vw 15vw;
    gap: 1.6vw;
    font-size: 0.72rem;
  }

  .consultation-choice small,
  .consultation-choice strong {
    font-size: 0.68rem;
  }

  .modality-choice {
    padding: 1.8vw 2vw;
    min-height: max(34px, 9.5vw);
    font-size: 0.7rem;
    line-height: 1.2;
    border-radius: var(--sr-rad-control);
  }

  .consultation-choice.active,
  .consultation-choice.active span,
  .modality-choice.active,
  .slot-btn.selected,
  .calendar-day.selected,
  .calendar-day.selected .calendar-day-num {
    color: var(--color-text-primary);
  }

  .consultation-choice.active small,
  .consultation-choice.active strong {
    color: var(--color-text-primary);
  }

  textarea.input-field {
    min-height: max(34px, 9.5vw);
    height: max(34px, 9.5vw);
    padding: 2.2vw 2.6vw;
    font-size: 0.72rem;
  }

  .booking-cost-row {
    margin-bottom: 6px;
    font-size: 0.76rem;
  }

  #btnProceedToPayment {
    min-height: var(--sr-tap-min);
    padding: 2vw 3vw;
    font-size: 0.68rem;
    letter-spacing: 2px;
    border-radius: var(--sr-rad-control);
  }

  .articles-header {
    margin-bottom: 0.7rem;
  }


  .category-filter {
    gap: 1.6vw;
    margin-bottom: 0.65rem;
    padding-bottom: 0;
  }

  .category-tab {
    padding: 2vw 2.6vw;
    font-size: 0.64rem;
    letter-spacing: 1.4px;
    min-height: max(30px, 8.5vw);
  }

  /* padding + radius now come from the cell tokens (agent-managed) */
  .product-card {
    min-height: 0;
  }

  .product-category {
    margin-bottom: 4px;
  }

  .product-name {
    font-size: 0.9rem;
    margin-bottom: 5px;
  }

  .product-desc {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 0.76rem;
    line-height: 1.42;
    margin-bottom: 0.7rem;
  }

  .product-footer {
    padding-top: 0;
  }

  .product-price {
    font-size: 0.92rem;
  }

  .product-btn-buy {
    height: max(28px, 8vw);
    padding: 0 3vw;
    font-size: 0.62rem;
    letter-spacing: 1.4px;
  }
}

/* Landscape: panels scroll internally instead of growing the page.
   The max-height that used to live here recomputed the available area by hand
   — 100svh minus the nav minus twice the padding — for three views named one by
   one, which is why Artículos and Cursos ended up 40px taller than the rest.
   The view's own content box already IS that area, so Window h governs the
   height for every tab and this rule only decides how overflow behaves. */
@media (orientation: landscape) {
  .section-panel {
    overflow-y: auto;
  }

  /* Height comes from Window h. Only the overflow is this panel's own business:
     its grid pins the booking footer in view instead of scrolling the panel. */
  #schedulerContainer {
    overflow: hidden;
  }

  .scheduler-grid,
  .contact-grid,
  .admin-layout {
    min-height: 0;
  }
}
