/* Webfonts — Spectral (display), Manrope (UI), JetBrains Mono (meta). */
@import url("https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,400;0,500;0,600;0,700;1,400&family=Manrope:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap");

:root {
  /* ── Neutrals & surfaces (warm stone) ── */
  --canvas: #F2F0EB;          /* app background */
  --surface: #FFFFFF;         /* cards, panels */
  --surface-alt: #FAF8F3;     /* inset / striped rows */
  --shell: #2B251E;           /* deep espresso sidebar */
  --shell-alt: #3A332A;       /* sidebar hover / active */

  /* ── Text ── */
  --ink: #26221C;             /* primary text */
  --text-secondary: #5A534A;
  --text-muted: #8C857A;
  --text-faint: #B3ABA0;
  --on-dark: #EDE8DF;
  --on-dark-muted: #A7A096;

  /* ── Lines ── */
  --line: #E7E1D7;
  --line-2: #F0EBE2;

  /* ── Primary accent — Champagne & Gold ── */
  --accent: #B08D57;
  --accent-hover: #927443;
  --accent-deep: #6E5530;
  --accent-soft: #F3ECDD;
  --accent-line: #E4D6BC;
  --accent-on-dark: #D8B878;  /* gold that reads on espresso */

  /* ── Status ── */
  --success: #4E7A5E;  --success-soft: #E7F0EA;
  --warning: #B5852F;  --warning-soft: #F6EBD6;
  --danger:  #9A5A5A;  --danger-soft:  #F2E6E6;
  --neutral: #8C857A;  --neutral-soft: #F0EBE2;

  /* ── Category tones — charts, staff, tags ── */
  --cat-forest: #5E7B62;
  --cat-rust:   #9A6A6A;
  --cat-blue:   #7E8BA6;
  --cat-mauve:  #8A6A85;
  --cat-sage:   #7A8B6F;
  --cat-gold:   #B08D57;

  /* ── Alternate accent themes (swap --accent* to retheme) ── */
  --theme-champagne: #B08D57;
  --theme-rose:      #B07A86;
  --theme-sage:      #7A8B6F;
  --theme-mauve:     #8A6A85;
  --theme-blue:      #7E8BA6;
  --theme-noir:      #3A332A;
}

:root {
  /* ── Families ── */
  --font-display: "Spectral", Georgia, "Times New Roman", serif;   /* voice, headlines, numerals */
  --font-sans: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; /* UI + body */
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace; /* eyebrows, SKUs, meta */

  /* ── Type scale ── */
  --text-display: 52px;
  --text-h1: 40px;
  --text-h2: 30px;
  --text-title: 19px;
  --text-body: 15px;
  --text-small: 13px;
  --text-eyebrow: 11px;

  /* ── Weights ── */
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* ── Tracking ── */
  --tracking-wordmark: 0.18em;  /* RINGUPS lockup */
  --tracking-eyebrow: 0.14em;   /* mono eyebrows, uppercase */
}

:root {
  /* ── Spacing — 4px base ── */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;
  --space-12: 48px;

  /* ── Radius ── */
  --radius-sm: 6px;    /* chips, inputs */
  --radius-md: 9px;    /* buttons */
  --radius-lg: 14px;   /* cards, modals */
  --radius-pill: 999px;

  /* ── Elevation ── */
  --shadow-card: 0 1px 2px rgba(40, 34, 26, 0.04);
  --shadow-raised: 0 6px 18px rgba(40, 34, 26, 0.10);
  --shadow-pop: 0 12px 32px rgba(40, 34, 26, 0.16);
}


/* Generated from style-hover attributes in the prototype. */
[data-h="h0"]:hover{color:var(--accent-on-dark)}
[data-h="h1"]:hover{color:#fff}
[data-h="h2"]:hover{background:var(--accent-hover)}
[data-h="h3"]:hover{background:var(--accent-soft)}
[data-h="h4"]:hover{background:rgba(255,255,255,0.24)}
[data-h="h5"]:hover{color:var(--ink)}
[data-h="h6"]:hover{background:var(--surface-alt)}
[data-h="h7"]:hover{background:rgba(255,255,255,0.18)}
[data-h="h8"]:hover{background:var(--shell-alt)}
[data-h="h9"]:hover{background:rgba(255,255,255,0.22)}
[data-h="ha"]:hover{border-color:var(--accent-line);transform:translateY(-3px)}
[data-h="hb"]:hover{color:var(--accent-deep)}
[data-h="hc"]:hover{background:rgba(255,255,255,0.26)}

/* Baseline the prototype assumed from the design-tool shell. */
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--canvas);color:var(--ink);font-family:var(--font-sans),system-ui,sans-serif;-webkit-font-smoothing:antialiased;overflow-x:hidden}
img{max-width:100%;height:auto}
a{color:inherit}

/* See wrapTables(). max-width keeps the scroller itself inside its column. */
.r-tscroll{overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%}

/* ------------------------------------------------------------------- motion
   A small, named vocabulary the pages compose from, rather than each page
   inventing its own keyframes inline. Two rules govern all of it:

   1. Nothing here may change layout. Every animated property is transform,
      opacity or filter, so none of it can reflow the page or shift a heading
      under a reader's finger mid-sentence.
   2. Every one of them is off under prefers-reduced-motion. The block at the
      bottom is not decoration - a bridal site is read by people planning a
      wedding on a phone, and motion sickness is not an edge case.

   .ru-reveal is the base: elements ship at opacity 0 and site.js adds .ru-in
   when they enter the viewport, with three separate fallbacks so a page can
   never render blank. */
.ru-reveal{opacity:0;transform:translateY(18px);transition:opacity .7s cubic-bezier(.2,.7,.3,1),transform .7s cubic-bezier(.2,.7,.3,1)}
.ru-reveal.ru-in{opacity:1;transform:none}

/* Children arrive in sequence rather than as one block. Capped at 10 so a long
   list cannot end up with a two-second tail nobody waits for. */
.ru-stagger>*{opacity:0;transform:translateY(16px);transition:opacity .6s cubic-bezier(.2,.7,.3,1),transform .6s cubic-bezier(.2,.7,.3,1)}
.ru-stagger.ru-in>*{opacity:1;transform:none}
.ru-stagger.ru-in>*:nth-child(1){transition-delay:0ms}
.ru-stagger.ru-in>*:nth-child(2){transition-delay:70ms}
.ru-stagger.ru-in>*:nth-child(3){transition-delay:140ms}
.ru-stagger.ru-in>*:nth-child(4){transition-delay:210ms}
.ru-stagger.ru-in>*:nth-child(5){transition-delay:280ms}
.ru-stagger.ru-in>*:nth-child(6){transition-delay:350ms}
.ru-stagger.ru-in>*:nth-child(7){transition-delay:420ms}
.ru-stagger.ru-in>*:nth-child(8){transition-delay:490ms}
.ru-stagger.ru-in>*:nth-child(n+9){transition-delay:560ms}

/* Cards. The shadow does the work; the 2px is what the eye registers. */
.ru-lift{transition:transform .35s cubic-bezier(.2,.7,.3,1),box-shadow .35s ease,border-color .35s ease}
.ru-lift:hover{transform:translateY(-3px);box-shadow:0 18px 38px -18px rgba(38,34,28,.30);border-color:var(--accent-line)}

/* Photography. .ru-fig is the frame; .ru-kb gives a hero a slow drift so a
   still photograph is not completely inert behind live type. */
.ru-fig{position:relative;overflow:hidden;border-radius:var(--radius-lg);background:var(--surface-alt)}
.ru-fig>img{display:block;width:100%;height:100%;object-fit:cover}
.ru-fig.ru-lift:hover>img{transform:scale(1.035)}
.ru-fig>img{transition:transform .7s cubic-bezier(.2,.7,.3,1)}
.ru-kb>img{animation:ru-kb 26s ease-in-out infinite alternate;will-change:transform}
@keyframes ru-kb{from{transform:scale(1) translate3d(0,0,0)}to{transform:scale(1.075) translate3d(0,-1.2%,0)}}

/* Aspect frames, so a 2:3 studio portrait and a 3:2 landscape can sit in the
   same grid without one of them dictating the row height. */
.ru-2x3{aspect-ratio:2/3}
.ru-4x5{aspect-ratio:4/5}
.ru-1x1{aspect-ratio:1/1}
.ru-3x2{aspect-ratio:3/2}
.ru-16x9{aspect-ratio:16/9}

/* The espresso scrim. Used wherever white type sits over a photograph; having
   one definition means the contrast ratio was decided once. */
.ru-scrim{position:absolute;inset:0;background:linear-gradient(180deg,rgba(38,34,28,.46) 0%,rgba(38,34,28,.70) 46%,rgba(38,34,28,.94) 100%)}
.ru-scrim-l{position:absolute;inset:0;background:linear-gradient(90deg,rgba(38,34,28,.92) 0%,rgba(38,34,28,.62) 45%,rgba(38,34,28,.18) 100%)}

/* Type sitting on a scrim gets a shadow as well as the gradient. The gradient
   handles a 50px heading on its own; an 11px mono eyebrow in gold, tracked out
   over a rail of hangers, does not - at that size the glyph strokes are thinner
   than the detail behind them and the letters read as smeared rather than as
   low-contrast. Inherited by everything in the hero content, which is the
   sibling that follows the scrim. */
.ru-scrim ~ *,.ru-scrim-l ~ *{text-shadow:0 1px 3px rgba(20,17,13,.62)}

/* A gold hairline that draws itself in. Cheap, and it gives a section heading
   something to resolve onto. */
.ru-rule{height:1px;background:var(--accent);transform:scaleX(0);transform-origin:left;transition:transform .9s cubic-bezier(.2,.7,.3,1) .1s}
.ru-in .ru-rule,.ru-rule.ru-in{transform:scaleX(1)}

/* Primary CTA. One slow sweep of champagne on hover - the only ornamental
   animation on the site, reserved for the one element we want clicked. */
.ru-cta{position:relative;overflow:hidden;isolation:isolate}
.ru-cta::after{content:"";position:absolute;inset:0;z-index:-1;transform:translateX(-100%);
  background:linear-gradient(100deg,transparent 0%,rgba(255,255,255,.20) 45%,transparent 70%);
  transition:transform .8s cubic-bezier(.2,.7,.3,1)}
.ru-cta:hover::after{transform:translateX(100%)}

/* Sticky in-page contents for the long pages. */
.ru-sticky{position:sticky;top:88px}

/* ------------------------------------------------------------------- nav
   Mega-menu dropdowns. Nav.dc.html is a PARTIAL - inlined into every page's
   <body>, never given the <helmet> treatment a page gets - so its own <style>
   tag would have to duplicate itself 33 times per build rather than living once
   in the shared stylesheet. These rules exist here for that reason.

   Reveal is CSS-only: :hover for a mouse, :focus-within for a keyboard tabbing
   through the trigger link. No JS state, so it costs nothing to maintain and
   cannot desync from the page. Below the 880px breakpoint .ru-nav-drop is
   irrelevant - the mobile panel Nav.dc.html renders instead lists every link
   flat under its own section heading, since a nested tap-to-expand menu is a
   second interaction model to test for one menu that already unfolds by
   scrolling. */
.ru-nav-drop{position:relative}
.ru-nav-trig{display:flex;align-items:center;gap:5px;cursor:default}
.ru-nav-trig svg{transition:transform .15s ease}
.ru-nav-drop:hover .ru-nav-trig svg,.ru-nav-drop:focus-within .ru-nav-trig svg{transform:rotate(180deg)}
.ru-nav-panel{
  position:absolute;top:100%;left:50%;transform:translateX(-50%) translateY(6px);
  margin-top:14px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius-lg);box-shadow:0 24px 48px -20px rgba(38,34,28,.28);
  padding:22px;opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .15s ease,transform .15s ease;z-index:60;
}
.ru-nav-drop:hover .ru-nav-panel,.ru-nav-drop:focus-within .ru-nav-panel{
  opacity:1;visibility:visible;pointer-events:auto;transform:translateX(-50%) translateY(0);
}
/* A borderless bridge so the mouse can travel from the trigger to the panel
   without the gap between them counting as "left the menu". */
.ru-nav-panel::before{content:"";position:absolute;top:-14px;left:0;right:0;height:14px}
.ru-nav-cols{display:grid;grid-template-columns:repeat(var(--cols,2),210px);gap:8px 28px}
.ru-nav-col-label{
  font-family:var(--font-mono);font-size:10px;letter-spacing:var(--tracking-eyebrow);
  text-transform:uppercase;color:var(--text-muted);margin:0 0 10px;padding-top:4px;
}
.ru-nav-link{
  display:block;padding:7px 8px;margin:0 -8px;border-radius:8px;text-decoration:none;
  font-size:13.5px;color:var(--text-secondary);white-space:nowrap;transition:background .12s,color .12s;
}
.ru-nav-link:hover{background:var(--accent-soft);color:var(--accent-deep)}
.ru-nav-panel-foot{
  grid-column:1/-1;margin-top:14px;padding-top:14px;border-top:1px solid var(--line-2);
}
.ru-nav-panel-foot a{
  font-size:12.5px;font-weight:600;color:var(--accent-hover);text-decoration:none;
}
.ru-nav-panel-foot a:hover{color:var(--accent-deep)}
@media (max-width:1180px){.ru-nav-cols{grid-template-columns:repeat(var(--cols,2),180px)}}

@media (prefers-reduced-motion:reduce){
  .ru-reveal,.ru-stagger>*{opacity:1;transform:none;transition:none}
  .ru-lift,.ru-fig>img,.ru-cta::after{transition:none}
  .ru-lift:hover{transform:none}
  .ru-kb>img{animation:none}
  .ru-rule{transform:scaleX(1);transition:none}
}

/* ---------------------------------------------------------------- responsive
   Overrides for the markers convert.mjs attaches. !important is not laziness
   here - it is the only thing that outranks an inline style, and the prototype
   is entirely inline-styled. Everything is scoped to the media query, so the
   desktop layout is bit-for-bit what it was. */
@media (max-width:860px){
  .r-grid{grid-template-columns:1fr!important}

  /* Tabular rows keep their columns and shrink, so the illustration still
     reads as the product rather than as a list of orphaned values. */
  .r-tab{font-size:9px!important;padding-left:10px!important;padding-right:10px!important;
         column-gap:6px!important;letter-spacing:0!important}
  .r-tab>*{min-width:0!important;overflow:hidden!important;text-overflow:ellipsis!important}

  .r-pad{padding-left:20px!important;padding-right:20px!important}
  .r-flex{flex-wrap:wrap!important}
  .r-w{width:100%!important;max-width:100%!important}
  .r-nowrap{white-space:normal!important}

  .r-fs-xl{font-size:31px!important;line-height:1.15!important;letter-spacing:-0.01em!important}
  .r-fs-lg{font-size:26px!important;line-height:1.2!important}
  .r-fs-md{font-size:21px!important;line-height:1.25!important}

  /* Section gutters. The markers catch elements that declare their own
     padding; these catch the layout wrappers that inherit it. */
  section{padding-left:20px!important;padding-right:20px!important}

  .r-pv{padding-top:40px!important;padding-bottom:40px!important}

  /* The desktop nav bar steps aside for the hamburger. */
  nav .r-flex{flex-wrap:nowrap!important}

  /* Decorative overhangs are removed rather than squeezed. There is no width
     on a phone for something to hang into, and the alternative is a photo
     sitting on top of the sentence underneath it. */
  .r-float{display:none!important}

  /* The in-page browser-chrome illustrations have their own fixed internal
     layouts. Scrolling one sideways is honest; letting it push the whole page
     wider is not. */
  [style*="border-radius:var(--radius-lg)"]{max-width:100%!important}

  /* Tap targets. Anything acting as a button gets a finger-sized hit area. */
  a[style*="border-radius"],button{min-height:44px}

  /* Long identifiers - style numbers, emails, URLs in the mock chrome - break
     rather than widen the page. */
  body{word-break:break-word;overflow-wrap:anywhere}

}

/* Above the nav's own breakpoint the hamburger and its drawer step aside.
   880px is the number the prototype's own logic uses; matching it keeps one
   breakpoint rather than two that disagree by twenty pixels. */
@media (min-width:880px){
  .r-mob,.r-drawer{display:none!important}
}
/* Below it, the desktop bar goes. 880px is the prototype's own number, so the
   swap happens at one width rather than two that disagree. */
@media (max-width:879px){
  .r-desk{display:none!important}
}

/* The drawer is closed until the hamburger says otherwise. Driven by an
   attribute on <nav> so there is exactly one piece of state.
   !important because the drawer carries an inline display:flex, which outranks
   a plain class - it rendered permanently open without this. */
.r-drawer{display:none!important}
nav[data-open="true"] .r-drawer{display:flex!important}

/* Phones proper. The bands above target tablets down; these are the sizes
   where the hero still needs to give way. */
@media (max-width:520px){
  .r-fs-xl{font-size:27px!important}
  .r-fs-lg{font-size:23px!important}
  .r-fs-md{font-size:19px!important}
  .r-pad{padding-left:16px!important;padding-right:16px!important}
  section{padding-left:16px!important;padding-right:16px!important}
}
