/* The gate's own layout. The look (page velvet or paper via .om on <body>, Montserrat, velvet square and its folded edge,
   cream text, fields, consent toggles, buttons, error line, tokens, theme) is om-design's: onlymatt.css and om-square.js,
   loaded from Bunny before this file; the theme is set by theme.js. */

:root {
  --font: var(--om-font);
  --pad-y: 16px;
  --pad-x: 18px;
  --gap: 10px;
  --size: min(calc(100vw - 32px), calc(100dvh - 32px), 440px);
  --pastille: 32px;  /* a round glass pastille (the legal signs, the globe) and the arrow that sends */
  --sign: 18px;      /* a sign drawn in a pastille */
  /* The signs (charte 13, principle 8), drawn as masks in the current colour: the shield (privacy), the document (terms). */
  --sign-shield: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3l7 3v5.5c0 4.4-3 7.7-7 9.5-4-1.8-7-5.1-7-9.5V6zM9 12l2.2 2.2L15.5 10'/%3E%3C/svg%3E");
  --sign-document: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 3h7l4 4v14H7zM14 3v4h4M9.5 12h5M9.5 15.5h5'/%3E%3C/svg%3E");
  /* A round glass pastille (principle 10): the « ? », the legal signs, the globe. Glass tokens of om-design when the
     stylesheet has them, the on-square ones otherwise. */
  --pastille-fill: var(--om-glass-strong, var(--om-on-square-fill));
  --pastille-edge: inset 1px 1px 0 var(--om-glass-edge, var(--om-on-square-line)), inset -1px -1px 0 var(--om-glass-shade, transparent);
  --pastille-blur: var(--om-glass-blur, none);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

/* Page: om-design's .om on <body> (velvet or paper, grain, breathing light). */
body { margin: 0; min-height: 100dvh; }

/* Over a site (widget.js frame): the body paints nothing; a fixed .om layer behind the square lets the site show
   through, by PAGE_OPACITY. Solid until the setting has arrived. */
.veil { display: none; position: fixed; inset: 0; z-index: -1; opacity: var(--page-opacity, 1); transition: opacity 0.4s ease; }
html.framed .veil { display: block; }
html.framed body { background: none; animation: none; }

/* The site's media full screen behind the veil (html.has-backdrop once the first one is here): the og:image first, the
   square media over it, one shown at a time, 0.6s cross-fade. Square sources fill the screen and are cropped at the
   centre; a missing medium simply never turns on. */
.backdrop { display: none; position: fixed; inset: 0; z-index: -2; overflow: hidden; background: var(--om-square); }
html.has-backdrop .backdrop, html.has-backdrop .veil { display: block; }
html.has-backdrop body { background: none; animation: none; }
/* The veil wears data-om-theme="dark" (index.html): the dark velvet of om-design, grain and breathing light included,
   whatever the theme; the paper of the light theme would wash the picture out. */
.backdrop > * {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.backdrop > .on { opacity: 1; }

.stage {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 16px;
}

/* The frame: the square (code, done and unsubscribe steps) or the grid (entry step), then the error line and
   the legal row. While the entry step is shown, the grid takes the square's place. */
.frame { display: flex; flex-direction: column; align-items: center; gap: var(--gap); }
.frame:has(> .grid-step:not([hidden])) > .card { display: none; }

/* The square: <om-square form> (om-design) holds the frame, the media and the content. */
.card { width: var(--size); }

/* The entry step on <om-media-grid> (om-design): the grid draws the windows on the site's picture; the gate only
   lays out what goes in each window. */
.grid-step { width: var(--size); }
/* The big square: the email only; the site's name and the logotype are read, not shown (principle 8). */
.mail-window { display: flex; flex-direction: column; justify-content: flex-end; gap: var(--gap); }
.mail-window .om-field { min-width: 0; width: 100%; text-overflow: ellipsis; }
/* The arrow that sends: its window stays a plain window on the picture until the email is a valid address; then the
   arrow comes (hidden, it leaves the tab order too). The words stay in the button for screen readers and come back
   on hover or focus. */
.send-window .om-btn { display: none; width: 100%; height: 100%; padding: 0; white-space: normal; }
#email-form:has(#email:valid) .send-window .om-btn { display: inline-flex; animation: tile-in 0.4s cubic-bezier(0.25, 0.8, 0.25, 1) both; }
@keyframes tile-in { from { opacity: 0; transform: scale(0.92); } to { opacity: 1; transform: none; } }
.send-window .sign { width: var(--pastille); height: var(--pastille); }
.send-window .word { font-size: 0; line-height: 1.25; }
.send-window .om-btn:is(:hover, :focus-visible) .sign { display: none; }
.send-window .om-btn:is(:hover, :focus-visible) .word { font-size: var(--om-text-xs, 12px); padding: 0 6px; }
/* On a phone the small windows are under 100px wide: tighter padding, the word at the small size. */
@media (max-width: 471px) {
  .gate-grid { --om-media-grid-pad: 6px; }
  .consent .label[data-short]::before { font-size: var(--om-text-xs, 12px); }
}
/* Until om-square.js has loaded: same size, same velvet, so nothing jumps. */
om-square:not(:defined) {
  display: block;
  aspect-ratio: 1 / 1;
  border-radius: var(--om-radius);
  background: var(--om-square-sheen);
  color: var(--om-on-square);
  box-shadow: var(--om-square-edge);
}

.content, .skeleton {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}
.content > *, .skeleton > * { flex-shrink: 0; }

.step { display: flex; flex-direction: column; gap: var(--gap); }

/* The ONLYMATT wordmark (om-design .om-wordmark, painted in the current colour) above the site's title. */
.wordmark { height: 12px; align-self: flex-start; color: var(--om-on-square-soft); }

h1 {
  margin: 0;
  font: 600 clamp(15px, 2.4vw, 20px) / 1.25 var(--font);
  letter-spacing: 0.01em;
}

p { margin: 0; }

.step > p, #code-label {
  font: 400 clamp(12px, 1.8vw, 14px) / 1.4 var(--font);
  color: var(--om-on-square-soft);
}

.bar {
  display: block;
  height: 14px;
  width: 55%;
  border-radius: 4px;
  background: var(--om-on-square-fill);
  animation: pulse 1.2s ease-in-out infinite;
}
.bar.wide { height: 20px; width: 70%; }
.bar.row { height: 38px; width: 100%; border-radius: var(--om-radius-inner); }
@keyframes pulse { 50% { opacity: 0.4; } }

/* A consent in its window: the window itself is the button. om-design's .om-check fills it (position:absolute),
   but here it is flat — no surface, no inner radius — so there is one square, not a square in a square. The word
   sits on the window; ticked, the whole window turns (clipped to its rounded corners by the tile's overflow).
   data-short is the one word shown; the full label stays in the DOM for screen readers; "optional" is read, not shown. */
.consent { position: relative; display: grid; }
.consent .om-check { position: absolute; inset: 0; }
.consent .label[data-short] { font-size: 0; }
.consent .label[data-short]::before { content: attr(data-short); font-size: var(--om-text-sm, 14px); }
.consent .optional { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
/* Flat in the grid: drop each control's own box so the window is the only square (no carré dans un carré). */
.gate-grid .consent .om-check { background: transparent; box-shadow: none; border-radius: 0; }
.gate-grid .consent .om-check:has(input:checked) { background: var(--om-on-square); color: var(--om-square); box-shadow: none; }
.gate-grid .consent.missing .om-check { box-shadow: inset 0 0 0 1.5px var(--om-on-square-danger); }
.gate-grid .mail-window .om-field { background: transparent; box-shadow: none; border-radius: 0; padding-left: 0; padding-right: 0; }
.gate-grid .mail-window .om-field:focus-visible { box-shadow: inset 0 0 0 1px var(--om-ink); }
.gate-grid .send-window .om-btn { position: absolute; inset: 0; border-radius: 0; }
/* The « ? » (principle 2): invisible at rest; a small glass « ? » in the corner on the window's hover or keyboard
   focus (on touch, when the grid is centred: .on); it opens into its words when it is hovered or focused in turn.
   The words stay in the DOM (transparent, never removed), so the button keeps its name for screen readers. */
.consent .why {
  position: absolute;
  top: 3px;
  right: 3px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  max-width: 24px;
  height: 24px;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: var(--om-radius-pill, 999px);
  font: 600 var(--om-text-xs, 12px) / 1 var(--font);
  white-space: nowrap;
  color: transparent;
  background: var(--pastille-fill);
  -webkit-backdrop-filter: var(--pastille-blur);
  backdrop-filter: var(--pastille-blur);
  box-shadow: var(--pastille-edge);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.25s ease, max-width 0.35s ease, padding 0.35s ease, color 0.25s ease;
}
.consent .why::before {
  content: "?" / "";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--om-on-square);
  transition: opacity 0.2s ease;
}
.consent:is(:hover, :focus-within) .why { opacity: 1; }
.consent .why:is(:hover, :focus-visible) { max-width: 120px; padding: 0 10px; color: var(--om-on-square-soft); }
.consent .why:is(:hover, :focus-visible)::before { opacity: 0; }
.consent .why:focus-visible { outline: 2px solid var(--om-on-square); outline-offset: 1px; }
@media (hover: none) {
  .gate-grid.on .consent .why { opacity: 1; }
}

/* Preferences screen (step 2b) in the square: the cookie and newsletter checkboxes in normal flow (not grid
   windows), each with its "Why?" link. om-design's .om-check styles the box and label; here it is only laid out. */
.prefs #prefs-list { display: flex; flex-direction: column; gap: var(--gap); margin-bottom: var(--gap); }
.prefs-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.prefs-row .om-check { flex: 1 1 auto; }
.prefs-row .why-link { flex: none; padding: 0; white-space: nowrap; }
#prefs-form { gap: var(--gap); }

form { display: grid; gap: 8px; margin: 0; }
.inline { display: flex; flex-wrap: wrap; gap: 6px; }
.step > .om-btn-link { align-self: flex-start; }
.inline .om-field { flex: 1 1 10rem; min-width: 0; }
input#code { letter-spacing: 0.3em; }

.done { font: 600 clamp(15px, 2.4vw, 20px) / 1.25 var(--font); }

/* Pop-ups and the language menu wear .om-square; only their size and placement are the gate's. */
dialog, .languages { font-family: var(--font); }
dialog {
  width: min(calc(100vw - 32px), 360px);
  padding: var(--pad-y) var(--pad-x);
  border: 0;
}
dialog::backdrop { background: var(--om-backdrop); }
dialog h2 { margin: 0 0 6px; font: 600 clamp(15px, 2.4vw, 18px) / 1.25 var(--font); }
dialog p { margin: 0 0 14px; font: 400 14px / 1.45 var(--font); color: var(--om-on-square-soft); }
dialog p + p { margin-top: -6px; }
dialog.om-square a { display: block; margin-bottom: 14px; color: var(--om-on-square); font-size: 13px; text-underline-offset: 3px; }
dialog form { justify-items: end; }
dialog .choices { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px 16px; }

/* Document pop-up: a frame on the page, a close button under it. */
dialog.doc { width: min(calc(100vw - 32px), 680px); height: min(calc(100dvh - 32px), 760px); padding: 0; }
dialog.doc[open] { display: grid; grid-template-rows: 1fr auto; }
dialog.doc iframe { width: 100%; height: 100%; min-height: 0; border: 0; }
dialog.doc .choices { padding: 12px var(--pad-x); }

/* Full pages linked from the pop-ups (.sheet also wears .om-square). */
.sheet {
  width: min(100%, 680px);
  padding: clamp(20px, 5vw, 36px) clamp(18px, 5vw, 40px);
}
.skeleton-flow { display: flex; flex-direction: column; gap: var(--gap); }
.sheet .wordmark { display: block; margin-top: 12px; }
.sheet h1 { margin: 12px 0 20px; }
/* Sections are separated by om-design's .om-fold (page.js), which brings its own margins. */
.sheet h2 { margin: 0 0 6px; font: 600 clamp(14px, 2vw, 16px) / 1.3 var(--font); }
.sheet p { font: 400 clamp(13px, 1.8vw, 15px) / 1.6 var(--font); color: var(--om-on-square-soft); }
.sheet p + p { margin-top: 8px; }
/* "Back" is om-design's button-link (.om-btn.om-btn-link, soft cream, underlined): its rule outweighs .om a on the paper theme. */
/* Inside the Document pop-up (html.embed, page.js): no page behind the sheet, the sheet fills the frame. */
html.embed body { background: none; animation: none; }
html.embed .stage { min-height: 0; padding: 0; }
html.embed .sheet { width: 100%; box-shadow: none; }

/* Astride the lower edge of the grid or the square, at every step (principle 10): three round glass pastilles of
   32px, the shield (privacy), the document (terms) and the globe (languages), quiet until the frame is hovered,
   focused or, on touch, centred. A sign instead of words (principle 8): the words stay in the link and come back on
   hover or focus. */
.legal {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  margin-top: calc(var(--pastille) / -2 - var(--gap));
  z-index: 2;
  font: 600 11px / 1.3 var(--font);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.6;
  transition: opacity 0.3s ease;
}
.frame:is(:hover, :focus-within) .legal { opacity: 1; }
@media (hover: none) {
  .frame:has(.gate-grid.on) .legal { opacity: 1; }
}
.legal a, .legal .lang {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  min-width: var(--pastille);
  max-width: var(--pastille);
  height: var(--pastille);
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: var(--om-radius-pill, 999px);
  font: inherit;
  white-space: nowrap;
  text-decoration: none;
  color: var(--om-on-square-soft);
  background: var(--pastille-fill);
  -webkit-backdrop-filter: var(--pastille-blur);
  backdrop-filter: var(--pastille-blur);
  box-shadow: var(--pastille-edge);
  cursor: pointer;
  transition: max-width 0.35s ease, padding 0.35s ease, color 0.25s ease;
}
.legal a { padding-left: calc((var(--pastille) - var(--sign)) / 2); color: transparent; }
.legal .lang { justify-content: center; }
.legal a::before {
  content: "";
  flex: none;
  width: var(--sign);
  height: var(--sign);
  background: var(--om-on-square-soft);
  -webkit-mask: var(--_sign) center / contain no-repeat;
  mask: var(--_sign) center / contain no-repeat;
}
.legal a[data-icon="privacy"] { --_sign: var(--sign-shield); }
.legal a[data-icon="terms"] { --_sign: var(--sign-document); }
.legal a:is(:hover, :focus-visible) { max-width: 260px; padding: 0 12px 0 calc((var(--pastille) - var(--sign)) / 2); color: var(--om-on-square-soft); }
.legal a:is(:hover, :focus-visible)::before { background: var(--om-on-square); }
.legal .lang:hover { color: var(--om-on-square); }
.legal :is(a, .lang):focus-visible { outline: 2px solid var(--om-on-square); outline-offset: 1px; }

/* Language menu: centered. */
.languages {
  margin: auto;
  padding: 6px;
  min-width: 180px;
  border: 0;
}
.languages::backdrop { background: var(--om-backdrop); }
.languages a {
  display: block;
  padding: 9px 12px;
  border-radius: var(--om-radius-inner);
  font: 400 14px / 1.3 var(--font);
  color: var(--om-on-square);
  text-decoration: none;
}
.languages a:hover { background: var(--om-on-square-fill); }
.languages a[aria-current] { font-weight: 600; }
.languages a[aria-current]::after { content: " ✓"; }

/* Bot trap: out of sight and out of reach for people. */
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

/* Read by screen readers, not shown. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Where the visitor comes from, readable while the square loads. */
.skeleton-host { margin: 0; font: 500 13px / 1.3 var(--font); color: var(--om-on-square-soft); }
.skeleton-host:empty { display: none; }

@media (prefers-reduced-motion: reduce) {
  html:not(.framed) body { animation: none; }
  .veil { animation: none; }
  .bar { animation: none; }
  .backdrop > * { transition: none; }
  .send-window .om-btn, .consent .why, .legal, .legal a, .legal .lang { animation: none; transition: none; }
}
