/*
 * Aya theme for Grist. Palette from the Aya tenders system (client/src/index.css), oklch
 * converted to hex to match how Grist writes its own themes.
 *
 * The `grist-custom` layer is declared last (cssVars.ts:310), so tokens in it win without
 * !important. Rules that must beat grainjs's runtime sheet sit outside it.
 *
 * ponytail: colours, font and logo only. Grist's layout is untouched.
 */

/* Heebo — the Aya UI font. Self-hosted so the app still works offline. */
@font-face {
  font-family: "Heebo";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("heebo-hebrew-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}

@font-face {
  font-family: "Heebo";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("heebo-latin-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF;
}

/* Hide the "Connect Grist to Claude and ChatGPT" promo: it advertises a full-edition feature in
   every edition (McpConnectBanner.ts:21). The inline gradient is the only stable hook, since the
   banner's grainjs class name is build-generated.
   ponytail: one-line patch to McpConnectBanner.buildDom() if this stops matching. */
[style*="rgb(41, 163, 163)"] {
  display: none !important;
}

/*
 * RTL: chrome and menus flip from `<html dir>` for free. Widget bodies are pinned back to ltr
 * because only the grid's horizontal maths is direction-aware (GridView.ts `_rtl`,
 * `_inlineScroll`, `getMousePosCol`), so it alone is released again below, as is a card's field
 * area. Which edge a cell's glyphs sit against is separate, and comes from the column's
 * alignment, whose per-type default is logical now (UserType.ts).
 *
 * Unlayered, to beat the components' own unlayered styles.
 * ponytail: audit DetailView and drop the pin rather than widening the exception list.
 */
[dir="rtl"] .viewsection_content {
  direction: ltr;
}

[dir="rtl"] .viewsection_content .gridview_data_pane {
  direction: rtl;
}

/* A card's field area only. Its row number, prev/next and active-record bar are unaudited. */
[dir="rtl"] .viewsection_content .g_record_detail_inner {
  direction: rtl;
}

/*
 * The data grid, Monday-style: a 36px lane, and Choice cells filled edge to edge with their
 * colour instead of a small pill floating inside them.
 *
 * Unlayered on purpose. grainjs `styled()` injects its rules unlayered at runtime and unlayered
 * beats every layer, so these carry two classes to win on specificity instead. Theme tokens are
 * the opposite case and stay in the layer: customCssParser.ts:19-34 reads only `:root` rules
 * there, and what it collects is what reaches custom-widget iframes.
 *
 * ponytail: paint only. Monday's collapsible colour-coded groups are a feature in GridView.ts.
 */

/* 18px line + 18px padding. Padding rather than line-height: viewCommon.css:134 sizes the
   row-height feature with a hardcoded `calc(3px + n * 18px)`. `.record` is grid-only. */
.record .field_clip {
  padding: 9px 8px;
}

/* The censored-cell lock is positioned against the old 3px padding. */
.record .field_clip.invalid.field-error-C::before {
  top: 10px;
}

/* Declared on .gridview_data_pane itself (GridView.css:14), so it has to be beaten there rather
   than on an ancestor. All six readers are in GridView.css, none in GridView.ts. */
.viewsection_content .gridview_data_pane {
  --gridview-header-height: 36px;
}

.column_names.record .column_name {
  font-weight: 500;
}

/*
 * Full-cell Choice colours. `.test-choice-token` is a test id but the only stable hook here --
 * ChoiceTextBox's class names are build-generated, and cssVars.ts:230 concedes `test-` ships in
 * production. It also marks single Choice only: a ChoiceList row of tokens stays pills.
 *
 * The token keeps `display: block` so its inherited `text-overflow: ellipsis` still applies. A
 * choice with no fillColor falls back to grey, which reads as broken at full-cell size -- set
 * the colours per choice in the right panel.
 */
.gridview_row .field_clip:has(> * > .test-choice-token) {
  padding: 0;
  display: flex;
}

.gridview_row .field_clip > * > .test-choice-token {
  flex: 1;
  height: auto;          /* over cssChoiceText's height: min-content */
  margin: 0;
  padding: 9px 8px;
  line-height: 18px;     /* same lane height as an ordinary cell */
  border-radius: 0;
  text-align: center;
  font-weight: 500;
}

/* No breadcrumb trail: the board header carries the name, and the trail restated the workspace
   and document over it. Hidden rather than deleted -- the same element holds the editable
   document name and the snapshot / unsaved / recovery-mode tags. `_cssDocBreadcrumbs` is a
   literal class breadcrumbs.ts carries; test-branding.mjs part 3 keeps it. */
._cssDocBreadcrumbs {
  display: none;
}

/*
 * A page showing one widget: no widget chrome, because the board header is the chrome. Stock
 * Grist frames every widget as a titled, bordered card floated inside two 12px gutters, all of
 * which says a second time what the header above already says.
 *
 * Only when the page has exactly one widget: ViewLayout.ts sets `viewlayout_solo` and drops it
 * for a tiled pair, which does need its titles and gutter to tell the two apart. Raw Data and
 * the record card popup build outside that root and keep theirs either way.
 *
 * Hiding the title bar itself lives in ViewLayout.css, not here: BoardHeader renders its search
 * and widget menu whether or not this stylesheet loads, so a build without it would draw both
 * of them twice.
 */
.viewlayout_solo .viewsection_content {
  margin: 0;
}

/*
 * No collapsed-widget tray on a board. A widget parked there is how a subitem source sits on the
 * page that uses it -- present but not drawn -- and upstream gives the tray a negative
 * page-padding margin, so it bleeds upward into what is now the header's buttons.
 *
 * Scoped to `viewlayout_solo`, which is the board case exactly: a page with one widget and a
 * collapsed source is solo, a tiled pair is not and keeps its tray. `collapsed_layout` is a
 * literal class LayoutTray.ts carries; test-branding.mjs part 3 keeps it.
 *
 * ponytail: a widget collapsed on a board page cannot be dragged back out, only reached from Raw
 * Data and the page's widget list. Say if that trade is wrong and this becomes a
 * GRIST_HIDE_UI_ELEMENTS feature instead, the way addNew is.
 */
.viewlayout_solo .collapsed_layout {
  display: none;
}

/* Flat on every page, not only a solo one: a widget is content, not a card. The gutter still
   separates a tiled pair, and the active-section bar is a box-shadow, which this does not touch. */
.view_data_pane_container {
  border: none;
}

/* On a solo page there is no second widget to tell it apart from, so the bar goes too. */
.viewlayout_solo .view_data_pane_container,
.viewlayout_solo .active_section > .view_data_pane_container {
  border: none;
  box-shadow: none;
}

/*
 * Reference cells as chips, like the Choice column above. Stock Grist prints a reference as bare
 * text, which reads as a typed-in value rather than a link to a record.
 *
 * A 16px line inside a 1px border is the 18px an ordinary cell has, so the chip costs the row
 * nothing. `.test-ref-text` is Reference.ts's hook for the name alone, not the surrounding "view
 * as card" icon; test-branding.mjs part 3 keeps it alive.
 */
.record .field_clip > .test-ref-text:not(:empty) {
  display: inline-block;
  max-width: 100%;
  padding: 0 8px;
  border: 1px solid var(--grist-theme-decoration, var(--grist-color-dark-grey));
  border-radius: 100px;
  background-color: var(--grist-theme-bg-secondary, var(--grist-color-light-grey));
  line-height: 16px;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: top;
}

/*
 * Header row, de-boxed. The borders themselves die via the app-header-* tokens in the layer
 * below; what is left here is geometry AppHeader.ts:324,374 hardcodes -- 4px radii, the
 * welded-corner flattening when the left pane is open, and hover feedback, which stock Grist
 * expresses through border colour and so loses along with the borders.
 *
 * Three class levels, to out-rank grainjs's unlayered `.cssLeftPane-open .cssAppLogo` state
 * rules. The `_css*` literals are stable hooks AppHeader.ts carries; test-branding.mjs part 3
 * keeps them alive.
 */
._cssAppHeader ._cssAppHeaderBox {
  border-radius: 8px;
}

._cssAppHeader ._cssAppHeaderBox ._cssAppLogo {
  /* The tile bakes its own 8px rounded square into the SVG, so the box just has to not paint
     over it. Scoped to the header, so login and error pages keep the full-size flat mark. */
  --icon-GristLogo: url("aya-mark-tile.svg");
  --grist-theme-logo-bg: transparent;
  --grist-theme-logo-size: contain;
  border-radius: 8px;
}

._cssAppHeader ._cssAppHeaderBox ._cssAppLogo:hover {
  filter: brightness(1.07);
}

._cssAppHeader ._cssAppHeaderBox ._cssOrg,
._cssAppHeader ._cssAppHeaderBox .cssOrgLink {
  border-radius: 8px;
}

._cssAppHeader ._cssAppHeaderBox ._cssOrg:hover,
._cssAppHeader ._cssAppHeaderBox .cssOrgLink:hover {
  background-color: var(--grist-theme-hover);
}

/* The org name is a bare grainjs div with no class of its own, but by construction the first
   child (AppHeader.ts:134,141). Its 16px lead-in was sized against a bordered box. */
._cssAppHeader ._cssOrg > div:first-child,
._cssAppHeader .cssOrgLink > div:first-child {
  padding-inline-start: 10px;
}

/* One mark of the workspace, not two: AppHeader already draws it at the top of the panel. Hidden
   rather than deleted, since it is also the hover target for the build and commit. The class is
   doubled to outrank the component's own `display: flex` -- grainjs injects its sheet at runtime,
   which is after this file's <link> however early it loads. */
.test-version-footer.test-version-footer {
  display: none;
}

/*
 * Five icons, not the set. Grist's are already thin-stroke outlines in much the same family as
 * Lucide, so a wholesale swap buys close to nothing. What stands out is a handful of solid-filled
 * glyphs among them, plus two that do not read: Help was a life-buoy, FieldInteger a bracketed [1].
 *
 * icons.css is in `@layer grist-base` and loads first (static/app.html:15), so this layer wins.
 * `url()` is relative to this file, which GRIST_STATIC_EXT_DIR serves alongside branding/icons.
 * test-branding.mjs part 4 checks each name against IconList and each file against disk.
 */
@layer grist-custom {
  :root {
    --icon-Warning: url("icons/Warning.svg");
    --icon-Pivot: url("icons/Pivot.svg");
    --icon-Folder: url("icons/Folder.svg");
    --icon-Help: url("icons/Help.svg");
    --icon-FieldInteger: url("icons/FieldInteger.svg");
  }
}

@layer grist-custom {
  :root {
    --grist-theme-font-family: "Heebo", -apple-system, sans-serif;
    --grist-theme-font-family-data: "Heebo", -apple-system, sans-serif;

    /* Aya azure. Hover/active states walk down the brand gradient (#42cbfc -> #0470a4). */
    --grist-theme-primary: #009fe2;
    --grist-theme-primary-muted: #0470a4;
    --grist-theme-primary-dim: #035a85;
    --grist-theme-primary-emphasis: #b8e6fa;
    --grist-theme-primary-translucent: rgba(0, 159, 226, 0.5);

    /* A whole shorthand with Grist's green written into it literally (GristLight.ts), so unlike
       every other control token it did not follow --primary. A var reference resolves per
       appearance, so the dark block needs no copy. */
    --grist-theme-control-border: 1px solid var(--grist-theme-primary);

    /* The page the reader is on. Stock Grist paints it bg-emphasis (#262633), a near-black slab
       down the panel. -muted for the text: #009fe2 on its own tint is 2.2:1. */
    --grist-theme-left-panel-active-page-bg: var(--grist-theme-primary-emphasis);
    --grist-theme-left-panel-active-page-fg: var(--grist-theme-primary-muted);

    --grist-theme-body: #333333;
    --grist-theme-emphasis: #161b1d;

    --grist-theme-bg-default: #ffffff;
    --grist-theme-bg-secondary: #f8fafc;
    --grist-theme-bg-tertiary: #eef0f3;

    --grist-theme-decoration: #dde1e5;
    --grist-theme-decoration-secondary: #eef0f3;
    --grist-theme-decoration-tertiary: #dde1e5;

    --grist-theme-secondary: #5c6c73;
    --grist-theme-secondary-muted: #8a969b;

    /* Stock Grist pairs near-black column headers (Base.ts:172) with mid-grey gridlines, which is
       the wrong way round. Quiet headers over hairlines instead. */
    --grist-theme-table-header-fg: #5c6c73;
    --grist-theme-table-header-border: #dde1e5;
    --grist-theme-table-body-border: #eef0f3;

    /* Darkened off Monday's literal hue (#e2445c, #fdab3d) to clear 4.5:1 as text against white:
       these tokens feed errorText/warning colour, not just fills. Info is Aya's own. */
    --grist-theme-error: #de2b46;
    --grist-theme-warning: #a76002;
    --grist-theme-info: #2563eb;

    /* Cursor and selection follow the brand instead of Grist green. */
    --grist-theme-token-cursor: #009fe2;
    --grist-theme-token-selection: rgba(0, 159, 226, 0.15);
    --grist-theme-token-selection-opaque: #dcf0fd;
    --grist-theme-token-selection-darker-opaque: #cbe8fb;
    --grist-theme-token-selection-darker: rgba(0, 159, 226, 0.25);
    --grist-theme-token-selection-darkest: rgba(0, 159, 226, 0.35);
    --grist-theme-token-hover: rgba(0, 159, 226, 0.08);

    /* Aya's --radius-sm (0.625rem * 0.6). Grist ships 4px. */
    --grist-theme-control-border-radius: 8px;

    /*
     * Type scale. Grist's own runs 8/10/11/13/14/16/18/20/22 (themes/Base.ts:44), nearly linear,
     * so nothing on the page outranks anything else. This opens the top end and lifts the floor.
     *
     * medium-font-size is load-bearing: cssVars.ts:217 sets it as `html { font-size }`, so it is
     * also what 1rem resolves to app-wide, grid cells included. Stored column widths are px and
     * do not follow, so text wraps ~8% sooner in existing docs.
     * ponytail: pin the grid back with `.gridview_data_scroll { font-size: 13px }` if the client
     * wants dense tables with roomy chrome.
     */
    --grist-theme-x-small-font-size: 11px;
    --grist-theme-small-font-size: 12px;
    --grist-theme-medium-font-size: 14px;
    --grist-theme-intro-font-size: 15px;
    --grist-theme-large-font-size: 18px;
    --grist-theme-x-large-font-size: 21px;
    --grist-theme-xx-large-font-size: 25px;
    --grist-theme-xxx-large-font-size: 30px;

    /* Heebo is variable (100-900), so heavier headings cost nothing extra to load. */
    --grist-theme-big-control-font-size: 14px;
    --grist-theme-header-control-font-size: 26px;
    --grist-theme-big-control-text-weight: 600;
    --grist-theme-header-control-text-weight: 700;

    /* Grist pairs a 20px blur with a 0.6-alpha grey (menus.ts:174), which smudges rather than
       lifts. Geometry is hardcoded in the components; only the colour is a token. */
    --grist-theme-menu-shadow: rgba(16, 24, 40, 0.14);
    --grist-theme-modal-shadow-inner: rgba(16, 24, 40, 0.14);
    --grist-theme-modal-shadow-outer: rgba(16, 24, 40, 0.06);
    --grist-theme-popup-shadow-inner: rgba(16, 24, 40, 0.14);
    --grist-theme-popup-shadow-outer: rgba(16, 24, 40, 0.06);

    /*
     * Marks, served from this directory via GRIST_STATIC_EXT_DIR. Two colourways of the same
     * geometry: aya-mark.svg flat blue for login/error/admin pages, aya-mark-tile.svg white on a
     * rounded gradient square for the app header (scoped there, above). logo-size is
     * `background-size` verbatim (AppHeader.ts:338) and the flat mark is 312x180, so a width plus
     * `auto` keeps its ratio where Grist's square default would squash it ~40%.
     */
    --icon-GristLogo: url("aya-mark.svg");
    --grist-theme-logo-bg: #ffffff;
    --grist-theme-logo-size: 90% auto;

    /* Transparent borders also retire the hover divider (--middle-border-color) without touching
       the component. These tokens are read nowhere but AppHeader. */
    --grist-theme-app-header-bg: transparent;
    --grist-theme-app-header-border: transparent;
    --grist-theme-app-header-border-hover: transparent;
  }

  :root[data-grist-appearance="dark"] {
    --grist-theme-primary: #2bbdf5;
    --grist-theme-primary-muted: #009fe2;
    --grist-theme-primary-dim: #0470a4;
    --grist-theme-primary-emphasis: #cbe8fb;
    --grist-theme-primary-translucent: rgba(43, 189, 245, 0.5);

    --grist-theme-body: #f9fbfb;
    --grist-theme-emphasis: #ffffff;

    --grist-theme-bg-default: #161b1d;
    --grist-theme-bg-secondary: #090b0c;
    --grist-theme-bg-tertiary: #22292b;

    --grist-theme-decoration: #333e41;
    --grist-theme-decoration-secondary: #22292b;
    --grist-theme-decoration-tertiary: #333e41;

    --grist-theme-secondary: #9ca8ab;
    --grist-theme-secondary-muted: #6f7b7e;

    /* Dark already draws hairlines (GristDark.ts:100-101); only the headers shout. */
    --grist-theme-table-header-fg: #9ca8ab;

    /* Lightened the same way stock Grist lightens its own error/warning for dark, keeping hue. */
    --grist-theme-error: #f47b8d;
    --grist-theme-warning: #fcb85f;
    --grist-theme-info: #60a5fa;

    --grist-theme-token-cursor: #2bbdf5;
    --grist-theme-token-selection: rgba(43, 189, 245, 0.15);
    --grist-theme-token-selection-opaque: #1b3a48;
    --grist-theme-token-selection-darker-opaque: #204657;
    --grist-theme-token-selection-darker: rgba(43, 189, 245, 0.25);
    --grist-theme-token-selection-darkest: rgba(43, 189, 245, 0.35);
    --grist-theme-token-hover: rgba(43, 189, 245, 0.08);

    /* Light derives these from primary-emphasis and -muted, and dark moves both inputs the other
       way, so the open page came out a near-white slab carrying #009fe2 at 2.34:1. 5.6:1 here. */
    --grist-theme-left-panel-active-page-bg: #1b3a48;
    --grist-theme-left-panel-active-page-fg: var(--grist-theme-primary);

    --grist-theme-logo-bg: #161b1d;

    /* Dark ships opaque black (GristDark.ts:204), which is the same smudge, harder. */
    --grist-theme-menu-shadow: rgba(0, 0, 0, 0.55);
    --grist-theme-modal-shadow-inner: rgba(0, 0, 0, 0.5);
    --grist-theme-modal-shadow-outer: rgba(0, 0, 0, 0.3);
    --grist-theme-popup-shadow-inner: rgba(0, 0, 0, 0.5);
    --grist-theme-popup-shadow-outer: rgba(0, 0, 0, 0.3);
  }
}
