/*
 * Web ADS base. Load after ads-tokens.css and before page styles:
 *
 *   <link rel="stylesheet" href="/static/ads/ads-tokens.css?v=...">
 *   <link rel="stylesheet" href="/static/ads/ads.css?v=...">
 *   <script type="module" src="/static/ads/ads.js?v=..."></script>
 *
 * Visual values come from ads-tokens.css, generated from Flutter ADS. This file
 * only holds what the web needs and Flutter ADS has no counterpart for.
 */

@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css');
/* Phosphor icons for page code, the same 2.1 release as Flutter's
   phosphor_flutter: <i class="ph ph-check">, ph-bold, ph-fill. Components
   draw the same glyphs inline (foundation/icons.js). */
@import url('https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.2/src/regular/style.css');
@import url('https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.2/src/bold/style.css');
@import url('https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.2/src/fill/style.css');
/* Tossface emoji (the version of the app's Tossface SVGs). --ads-font-family
   lists it right after Pretendard, before the system fonts (Safari's system
   font would otherwise draw Apple Color Emoji), so every emoji renders in
   Tossface while digits and symbols stay in Pretendard. tossface.css is our
   copy of the release's rules with valid unicode ranges; only the subsets in
   use download. */
@import url('tossface.css');
/* White-label brand colours: empty on main; a white-label branch sets its
   brand tokens there so this file and ads-tokens.css stay as on main. */
@import url('brand.css');

/*
 * Public styling hooks, set on the component element itself. Registered as
 * non-inheriting, so a hook set on a container never leaks into nested
 * components; each component forwards its own value into its shadow root.
 */
@property --ads-interaction-overlay-color { syntax: '*'; inherits: false; }
@property --ads-interaction-overlay-inset { syntax: '*'; inherits: false; }
@property --ads-list-item-padding-inline-start { syntax: '*'; inherits: false; }
@property --ads-list-item-padding-inline-end { syntax: '*'; inherits: false; }
@property --ads-list-item-padding-block { syntax: '*'; inherits: false; }
@property --ads-list-item-heading-font-size { syntax: '*'; inherits: false; }
@property --ads-list-item-heading-line-height { syntax: '*'; inherits: false; }
@property --ads-list-item-description-font-size { syntax: '*'; inherits: false; }
@property --ads-list-item-description-line-height { syntax: '*'; inherits: false; }
@property --ads-list-item-leading-size { syntax: '*'; inherits: false; }
@property --ads-list-item-leading-gap { syntax: '*'; inherits: false; }
@property --ads-accordion-body-indent { syntax: '*'; inherits: false; }
@property --ads-bottom-sheet-trailing-width { syntax: '*'; inherits: false; }
@property --ads-breadcrumb-item-max-width { syntax: '*'; inherits: false; }
@property --ads-pagination-item-size { syntax: '*'; inherits: false; }
@property --ads-pagination-current-background { syntax: '*'; inherits: false; }
@property --ads-pagination-current-color { syntax: '*'; inherits: false; }
@property --ads-pagination-current-font-weight { syntax: '*'; inherits: false; }
@property --ads-action-area-background { syntax: '*'; inherits: false; }
@property --ads-action-area-padding-inline { syntax: '*'; inherits: false; }
@property --ads-avatar-group-ring-color { syntax: '*'; inherits: false; }
/* avo-shimmer publishes its palette and sweep to the skeleton shapes inside
   it; the shift animates, so it is typed and inherited. */
@property --ads-shimmer-fill { syntax: '*'; inherits: true; }
@property --ads-shimmer-shift { syntax: '<length>'; inherits: true; initial-value: 0px; }

/* Dark skeletons do not reuse the light palette: white 6% to white 12%
   rests a little above the surface and sweeps a gentle step brighter (Flutter AvoShimmer.replacePalette, owner 2026-11-05). Overlay mode keeps its
   palette because it sweeps over images. */
:root[data-ads-theme="dark"] {
  --ads-shimmer-base: color-mix(in srgb, var(--ads-static-white) 6%, transparent);
  --ads-shimmer-highlight: color-mix(in srgb, var(--ads-static-white) 12%, transparent);
}

:root {
  /* Keyboard focus ring. Aliases of the shared tokens (stroke.focus,
     AvoInteractionTokens.focusRing*), which Flutter's AvoInteraction draws
     too; new code may read either name. */
  --ads-web-focus-outline-width: var(--ads-interaction-focus-ring-width);
  --ads-web-focus-outline-offset: var(--ads-interaction-focus-ring-offset);
  --ads-web-focus-outline-color: var(--ads-stroke-focus);
}

/*
 * Web-only line breaks, matching Flutter AvoText's `wrap`. Running text keeps
 * a word or more on its last line (pretty); display, title, heading, and
 * headline text and page headings split into lines of even length (balance).
 * Both inherit, so they reach component shadow roots too (textStyle() sets
 * balance there). Browsers without support wrap as before.
 */
:root {
  text-wrap: pretty;
}

h1,
h2,
h3,
[class*="avods-text-display"],
[class*="avods-text-title"],
[class*="avods-text-heading"],
[class*="avods-text-headline"] {
  text-wrap: balance;
}

/*
 * Smoothed corners, Figma corner smoothing 20% (owner, 2026-11-03), as
 * Flutter ADS draws them (AvoSmoothRectangleBorder, Figma's construction).
 * A corner of radius r smoothed by 20% starts curving 1.2r from the corner
 * and crosses the diagonal where a circular r does. Where CSS corner-shape
 * is supported, the radius tokens below span 1.2 times their value and
 * every rounded box that uses a token sets
 * `corner-shape: var(--ads-corner-shape)`, the superellipse that best fits
 * that curve (within 1px of Figma on every ADS box, small ones included,
 * where both clamp to half the box). Pills and circles (the full token, 50%)
 * stay round. Other browsers keep the generated radii and round corners.
 * tests/js/ads_contract.test.mjs checks these values against ads-tokens.css.
 */
:root {
  --ads-corner-shape: round;
}

@supports (corner-shape: superellipse(2)) {
  :root {
    --ads-corner-shape: superellipse(1.34);
    --ads-border-radius-3xs: 2.4px;
    --ads-border-radius-2xs: 7.2px;
    --ads-border-radius-xs: 9.6px;
    --ads-border-radius-sm: 14.4px;
    --ads-border-radius-md: 19.2px;
    --ads-border-radius-lg: 28.8px;
    --ads-control-xs-radius: 9.6px;
    --ads-control-sm-radius: 14.4px;
    --ads-control-md-radius: 14.4px;
    --ads-control-lg-radius: 19.2px;
  }
}

/*
 * Field labels shared by avo-select-field, avo-text-field, avo-text-area, and
 * standalone labels next to segmented controls. AvoTextField heading style:
 * label1 bold (w600) in label.neutral.
 */
.avo-form-field__label {
  color: var(--ads-fg-neutral-subtle);
  font-family: var(--ads-font-family);
  font-size: var(--ads-label1-font-size);
  font-weight: var(--ads-font-weight-semibold);
  line-height: var(--ads-label1-line-height);
  letter-spacing: var(--ads-label1-letter-spacing);
}

.avo-form-field__label-row {
  display: inline-flex;
  align-items: center;
  gap: var(--ads-size-4);
  width: max-content;
  max-width: 100%;
}

/* avo-count-stepper keeps its number input in the light DOM. WebKit draws
   the spin buttons as pseudo-elements, which ::slotted() cannot reach. */
avo-count-stepper > input::-webkit-inner-spin-button,
avo-count-stepper > input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/*
 * Hide web ADS elements until their module defines them, so slotted content
 * does not flash unstyled. Keep this list in step with ads.js
 * (tests/js/ads_contract.test.mjs checks it).
 */
:is(
  avo-accordion,
  avo-accordion-item,
  avo-action-area,
  avo-alert,
  avo-avatar,
  avo-avatar-group,
  avo-badge,
  avo-blocking-progress,
  avo-bottom-sheet,
  avo-breadcrumb,
  avo-breadcrumb-item,
  avo-button,
  avo-calendar,
  avo-callout,
  avo-checkbox,
  avo-circular-progress-indicator,
  avo-chip,
  avo-choice-tile,
  avo-content-header,
  avo-count-stepper,
  avo-date-field,
  avo-dialog,
  avo-divider,
  avo-empty-state,
  avo-file-drop,
  avo-help-bubble,
  avo-icon-button,
  avo-image-frame,
  avo-list-item,
  avo-month-field,
  avo-pagination,
  avo-popup-menu,
  avo-popup-menu-item,
  avo-popup-menu-section,
  avo-progress-bar,
  avo-progress-indicator,
  avo-progress-tracker,
  avo-progress-tracker-step,
  avo-radio,
  avo-search-field,
  avo-segmented-control,
  avo-select-field,
  avo-shimmer,
  avo-slider,
  avo-snackbar,
  avo-stepper,
  avo-switch,
  avo-tab,
  avo-tab-item,
  avo-table-pagination,
  avo-tag,
  avo-tag-group,
  avo-text-area,
  avo-text-button,
  avo-text-field,
  avo-time-field,
  avo-time-picker,
  avo-tooltip,
  avo-tooltip-block
):not(:defined) {
  visibility: hidden;
}

/* A standalone field label (one placed before its control instead of inside
   an ADS field) keeps the field heading's s8 to the control below, like the
   fields do (Flutter: heading, SizedBox(height: s8), then the field), in any
   container. Containers add no gap of their own between the two: left to
   them, it kept collapsing to 0 (owner, 2026-10-27). Legacy page CSS resets
   label margins with !important at any specificity, so these rules are
   !important inside a cascade layer: an important declaration in a layer
   wins over every unlayered one, whatever its specificity. */
@layer avods-field-label {
  :is(.avo-form-field__label, .avo-form-field__label-row):has(+ :is(
    avo-text-field, avo-text-area, avo-select-field, avo-segmented-control,
    avo-count-stepper, avo-file-drop, avo-date-field, avo-time-field, avo-month-field,
    compact-language-selector, select-dropdown,
    [role="group"], [role="radiogroup"]
  )) {
    display: block !important;
    margin-block-end: var(--ads-size-8) !important;
  }
  .avo-form-field__label-row:has(+ :is(
    avo-text-field, avo-text-area, avo-select-field, avo-segmented-control,
    avo-count-stepper, avo-file-drop, avo-date-field, avo-time-field, avo-month-field,
    compact-language-selector, select-dropdown,
    [role="group"], [role="radiogroup"]
  )) {
    display: flex !important;
  }
  /* A medium or small segmented control keeps a 44px touch target around a
     shorter track; the label gives that overhang back so the s8 is to the
     track you see (owner, 2026-10-29). */
  :is(.avo-form-field__label, .avo-form-field__label-row):has(+ avo-segmented-control[size="sm"]) {
    margin-block-end: calc(var(--ads-size-8) - (var(--ads-interaction-minimum-touch-target) - var(--ads-size-40)) / 2) !important;
  }
  :is(.avo-form-field__label, .avo-form-field__label-row):has(+ avo-segmented-control[size="xs"]) {
    margin-block-end: calc(var(--ads-size-8) - (var(--ads-interaction-minimum-touch-target) - var(--ads-size-32)) / 2) !important;
  }
}

/* Overlays render nothing until defined and opened. */
:is(avo-dialog, avo-bottom-sheet, avo-snackbar, avo-popup-menu, avo-tooltip, avo-help-bubble, avo-blocking-progress):not(:defined) {
  display: none;
}

/*
 * Emoji and other full-colour content (images, flags) in an icon slot. Icon
 * slots tint their content with a translucent label colour (label.alternative
 * and friends), and browsers apply that alpha to colour fonts too, which fades
 * Tossface. Mark such content .avods-emoji to keep it at full strength.
 */
.avods-emoji {
  color: #000;
  font-family: var(--ads-font-family);
}

/* A Tossface emoji leading a small chip reads at its 14px label size, not
   the 12px icon size, which shrinks it to a speck (CEFR level chips). */
avo-chip[size="xs"] > .avods-emoji:is([slot="leading"], [slot="trailing"]) {
  font-size: var(--ads-size-14);
  inline-size: var(--ads-size-14);
  block-size: var(--ads-size-14);
}
