/* Minimal app CSS for the AntikCocuk.V5 shell. FluentUI base tokens come from
   default-fuib.css (linked in App.razor before this file). */

/* ===========================================================================
   AVATAR SHAPE TOKEN — every avatar in the app is a rounded square (a
   squircle / app-icon shape), not a full circle, driven by ONE custom
   property so the radius never has to be hunted down and changed file by
   file again.

   Why 8px: this app's avatars run 28-48px on a side. At that range, 8px is
   17%-29% of the side (8/48 = 16.7%, 8/28 = 28.6%) — unmistakably a
   soft-cornered square, not a barely-rounded rectangle (which would read at
   a few percent of the side, not double digits).

   Deliberately NOT touched: the nav rail's school logo (100px,
   border-radius: 10px, in Components/Layout/NavMenu.razor.css — that file is
   off limits for this change). At 100px, 8px (this token) and 10px (its own
   hardcoded value) read as the same visual treatment, so leaving that one
   rule un-unified does not clash with this app-wide token.
   =========================================================================== */
:root {
    --avatar-radius: 8px;
}

/* FluentAvatar (<fluent-avatar>) is a web component, and rc.4's shadow-root
   stylesheet genuinely ships a square shape for it, keyed off the `shape`
   attribute Razor puts on the light-DOM host when you set
   Shape="AvatarShape.Square":
       :host { border-radius: var(--borderRadiusCircular); }
       :host([shape="square"]) { border-radius: var(--borderRadiusMedium); }
       :host([shape="square"][size="20"]), :host([shape="square"][size="24"])
         { border-radius: var(--borderRadiusSmall); }
       :host([shape="square"][size="56"]), :host([shape="square"][size="64"]),
         :host([shape="square"][size="72"]) { border-radius: var(--borderRadiusLarge); }
       :host([shape="square"][size="96"]), :host([shape="square"][size="120"]),
         :host([shape="square"][size="128"]) { border-radius: var(--borderRadiusXLarge); }
   So Shape="AvatarShape.Square" does square the host by itself — we are using
   a real library feature here, not fighting a hardcoded circle.

   That built-in square radius is a SIZE-KEYED SCALE, though, not one flat
   value: 2px (--borderRadiusSmall) at 20-24px, 4px (--borderRadiusMedium) at
   the unkeyed default, 6px (--borderRadiusLarge) at 56-72px, 8px
   (--borderRadiusXLarge) at 96-128px. Our one house token (--avatar-radius:
   8px above) deliberately flattens that whole scale to a single value, so a
   32px header avatar and a 40px student avatar read as the exact same shape
   instead of drifting apart by size the way rc.4's own scale would have them
   do.

   The one thing that scale does NOT cover is the slotted image itself:
       ::slotted(img) { box-sizing: border-box; width: 100%; height: 100%;
         border-radius: var(--borderRadiusCircular); }
   has no `[shape="square"]` variant at all — it stays circular
   unconditionally, no matter what the host's `shape` attribute says. That is
   exactly why the second rule below (`fluent-avatar[shape="square"] img`) is
   genuinely required and not redundant with the first: without it, the host
   frame would go square while the photo inside kept painting as a circle
   inside that square frame.

   Both rules below are document-level (light-DOM) selectors against that same
   host element and the `<img>` the caller slots into it as an ordinary child.
   That's why they take effect with no !important needed: a page-authored rule
   that targets a shadow host beats that host's own internal `:host` rules, so
   our two plain selectors override `:host([shape="square"])` and
   `::slotted(img)` above without having to win a specificity fight. */
fluent-avatar[shape="square"] { border-radius: var(--avatar-radius); }
fluent-avatar[shape="square"] img { border-radius: var(--avatar-radius); }

/* ===========================================================================
   SHELL GRID — full-height nav on the left, header inside the content column.

   rc.4's default is  "header header header" / "nav content aside" /
   "footer footer footer", i.e. the header spans the whole page and the nav
   starts under it. v4 does the opposite (v4 MainLayout.razor:5-28: a horizontal
   FluentStack whose first child is the full-height NavMenu, with MainHeader
   stacked above the body inside the second column), so this restores v4's shape.

   ⚠️ This override CANNOT live in MainLayout.razor.css. The grid <div> is
   rendered by the FluentLayout *component*, so it never receives MainLayout's
   b-xxxxxxxxxx CSS-isolation scope attribute, and ::deep has no page-authored
   ancestor to hang off (DESIGN-GUIDELINES.md, "Reason 2 — the scope attribute is
   never on the Fluent element"). It has to be global CSS or an inline Style=.

   ⚠️ It also needs BOTH the `div` prefix and the media query, and neither is
   cosmetic (both established by browser measurement, diary 0040):

   1. `div.` — rc.4's own `.fluent-layout { grid-template-areas: "header header
      header" … }` is (0,1,0), exactly the same specificity as a bare
      `.fluent-layout` here, and it WINS the tie on source order: the package's
      bundle.scp.css is pulled in by an `@import` on the FIRST LINE of the
      generated AntikCocuk.V5.styles.css, and App.razor links that file AFTER
      app.css. So every global override of a FluentUI component's own CSS must
      clear (0,1,0). `.fluent-layout` is always a <div> (FluentLayout's
      BuildRenderTree opens one literally), so `div.` is a free +1.

   2. The media query — because raising specificity above (0,1,0) would ALSO beat
      rc.4's mobile branch. FluentLayout emits an inline <style> whose container
      query resets grid-template-areas to "header"/"content"/"footer" below
      MobileBreakdownWidth, and that rule is also (0,1,0). Scoping this override
      to >=769px hands the mobile case straight back to rc.4 untouched, instead of
      re-implementing it. 769 is therefore coupled to FluentLayout's
      MobileBreakdownWidth (default 768) — change one, change the other. The
      container it queries is a plain div spanning the viewport with no scrollbar
      (default-fuib.css pins `body { height: 100dvh; overflow: hidden }`), so
      container width == viewport width; verified identical behaviour at 768 and
      769 in the browser.
   =========================================================================== */
@media (min-width: 769px) {
    div.fluent-layout {
        grid-template-areas:
            "nav header aside"
            "nav content aside"
            "nav footer aside";
        grid-template-columns: auto 1fr auto;
        grid-template-rows: auto 1fr auto;
    }
}

/* The hamburger lives inside the header band, which in this app is white
   (MainHeader.razor.css) rather than rc.4's brand blue. rc.4 paints the icon
   `fill: var(--colorNeutralForegroundOnBrand)` (white) on .fluent-layout-hamburger,
   AND hands the inner FluentButton `Color="var(--colorNeutralForegroundOnBrand)"`,
   which FluentButton.StyleValue writes out as an INLINE `color:` on the
   <fluent-button>. White on white, twice.

   Re-pointing the TOKEN on the hamburger element fixes both halves at once and is
   why there is no !important here: custom properties inherit, so the inline
   `color: var(--colorNeutralForegroundOnBrand)` on the descendant <fluent-button>
   resolves against this declaration too. (Overriding `fill`/`color` directly would
   have fixed only the half that is not inline.) Measured: the icon computes
   rgb(36,36,36).

   Global, not MainHeader.razor.css, for the same reason as the grid above: every
   element here is rendered by a FluentUI component and carries no b- scope
   attribute. `div.` for the same cascade reason (rc.4's own rules are @imported
   later — see above); the two hamburger rules below are (0,3,0) in rc.4 too. */
div.fluent-layout-item[area="header"] .fluent-layout-hamburger {
    --colorNeutralForegroundOnBrand: var(--colorNeutralForeground1);
}

/* rc.4 gives the hamburger `:hover { background-color: var(--colorBrandBackgroundPressed) }`
   — a dark blue block, correct on its brand-blue header, wrong on a white one. */
div.fluent-layout-item[area="header"] .fluent-layout-hamburger:hover {
    background-color: var(--colorNeutralBackground1Hover);
    border-radius: 4px;
}

h1:focus {
    outline: none;
}

.content {
    padding: 1.5rem;
}

.field-row {
    margin-bottom: 1rem;
    max-width: 320px;
}

/* GAG timeline cursor-following tooltip (rendered into document.body by
   js/gag-timeline.js, so it lives outside GagTimeline's component-scoped CSS -
   a JS-created element appended to <body> never receives Blazor's CSS
   isolation scope attribute). Copied verbatim from v4's app.css (diary 0026) -
   this is a fixed dark-chrome floating tooltip (near-black background, white/
   pastel text) by original design, not themed off the app's own light/dark
   mode, so it needs no [data-theme] variant. */
.gag-tip {
    position: fixed;
    z-index: 50;
    pointer-events: none;
    background: #0f172a;
    color: #fff;
    border-radius: 8px;
    padding: 8px 10px;
    font-size: 12px;
    line-height: 1.45;
    max-width: 260px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .25);
}

.gag-tip b {
    color: #fff;
}

.gag-tip .t-muted {
    color: #94a3b8;
}

.gag-tip .t-done {
    color: #34d399;
}

.gag-tip .t-missed {
    color: #fb7185;
}

.gag-tip .t-upcoming {
    color: #7dd3fc;
}

/* ===========================================================================
   DATA GRID FULL WIDTH — opt-in contract: the grid's BOX fills its container,
   and it KEEPS filling it after the user drags a column.

   Opt in per grid:  <CocukDataGrid … Class="data-grid-fullwidth" />
   Grids that do not carry the class are untouched — this whole block is inert
   for them.

   ⚠️ Two independent problems, one contract. The CSS below fixes the BOX; only
   js/datagrid-fullwidth.js fixes the TRACKS. Neither is sufficient alone.

   1. The cascade (why `table.` and not a bare class). rc.4 ships
      `.fluent-data-grid { … width: auto; flex: 1; … }` — specificity (0,1,0),
      extracted from the package's
      Microsoft.FluentUI.AspNetCore.Components.bundle.scp.css (5.0.0-rc.4-26180.1).
      There is NO `table.`-prefixed selector anywhere in that bundle, so (0,1,0)
      is the whole bar. But a TIE LOSES HERE: the bundle is pulled in by an
      `@import` on the FIRST LINE of the generated AntikCocuk.V5.styles.css, and
      App.razor links that file (line 13) AFTER app.css (line 12) — so the
      library's rules land after ours and win any equal-specificity contest on
      source order. We must EXCEED (0,1,0), not match it. `table.` is the free
      +1: the grid element is always a <table> (FluentDataGrid.razor opens one
      literally), making this selector (0,1,1).

      This is the same class of problem as `div.fluent-layout` at the top of
      this file, solved the same way and for the same reason — see the SHELL
      GRID banner's trap 1 for the full source-order argument.

      ⚠️ Mercury's copy of this comment says its rule wins "on the tie, because
      app.css loads AFTER the library bundle". That is true THERE and FALSE
      HERE — our link order is reversed. Do not copy that sentence back in.

   2. Why the CSS alone is not enough (MEASURED at 1440x900 on /anket-gruplari,
      GridTemplateColumns="2fr 1fr 1fr 1fr 400px"). With the AUTHORED template
      the table box is 1142px in a 1142px container and the resolved tracks sum
      to 1142px — gap 0. After reproducing rc.4's post-drag write (an all-pixel
      inline `grid-template-columns`) the table box is STILL 1142px, but the
      tracks now sum to 942px: 200px of dead space on the right, because no
      flexible track remains to reabsorb the slack. THE BOX WAS NEVER THE
      PROBLEM; THE TRACKS ARE. rc.4 writes that all-px template from three
      places in FluentDataGrid.razor.js — the column-drag `moveHandler` (which
      converts EVERY `minmax(...)` token to a pixel value), `ResizeColumnDiscrete`
      / `ResizeColumnExact`, and `AutoFitGridColumns`. It writes it INLINE on the
      element, which no stylesheet rule can outrank at any specificity, so the
      repair cannot be CSS: js/datagrid-fullwidth.js observes that inline write
      and puts one flexible track back. Read its header for the mechanism.

   Template requirements for a grid that opts in:
     • The authored `GridTemplateColumns` MUST contain at least one flexible
       (`fr`) track. That track is what the JS remembers and restores; a fully
       fixed template has nothing to reabsorb the slack and will strand dead
       space exactly as measured above.
     • `AutoFit="true"` is INCOMPATIBLE. `AutoFitGridColumns` produces an
       all-pixel template by design and additionally strips the `auto-fit`
       class, so the grid fights this contract permanently.
     • Do NOT supply column-level `Width=` together with `GridTemplateColumns`:
       rc.4 THROWS. (Verified in FluentDataGrid.razor.cs — `ArgumentException`,
       "You can use either the 'GridTemplateColumns' parameter on the grid or
       the 'Width' property at the column level, not both.")

   Scope note — this contract owns WIDTH ONLY, and still does. Row height is a
   separate app-wide rule; see the GRID ROW HEIGHT banner below. Opting a grid
   into full width here never changes its row heights, so the class stays safe to
   add anywhere. (Mercury scopes its own row spacing to this class, in its own
   app.css:98 — `.data-grid-fullwidth td, th { min-height: 44px }`. That SHAPE
   was deliberately not copied: ours has to reach EVERY grid, including the ones
   without this class, because it replaces a constructor-level default that did.)

   Note: 25 of this app's 33 grids already carry an inline `Style="width: 100%"`.
   Inline beats any stylesheet, so their BOX is already correct today; the class
   replaces that scattered inline with one named contract and additionally covers
   the 8 grids that lack it.
   =========================================================================== */
table.data-grid-fullwidth {
    width: 100%;
}

/* ===========================================================================
   GRID ROW HEIGHT — 58px data rows, 40px headers, app-wide. THIS RULE IS THIS
   APP'S ROW HEIGHT. It is not a workaround and it has no removal condition.

   Where it came from: the height used to be `RowSize = DataGridRowSize.Large`
   in CocukDataGrid's constructor. rc.4 turns `RowSize` into an INLINE `height`
   on the cell — `FluentDataGridCell<TGridItem>.StyleValue` adds
   `height: {(int)Grid.RowSize}px` with NO CellType/RowType guard — and
   `BuildRenderTree` hands that same StyleValue to the <th> as to the <td>. So
   asking for 58px rows also produced 58px HEADERS. That was issue #329.

   Why a stylesheet rule reaches an inline height, with no `!important`:
   IT DOESN'T FIGHT IT, IT CLAMPS IT. `min-height` and `height` are different
   properties, so there is no cascade contest, no specificity problem and no
   source-order problem. Used height is clamp(min-height, height, max-height),
   so this `min-height: 58px` wins over the inline `height: 32px` (rc.4's own
   default RowSize, Small) outright.

   Why the HEADER stays out of it, for free: rc.4 also writes an INLINE
   `min-height: 40px` on every cell whose row type is not Default — i.e. on
   `header` and `sticky-header` rows and nothing else. Inline DOES beat a
   stylesheet on the same property, so the header keeps its own 40px floor and
   this rule cannot reach it even if the selector were widened to `th`. That
   asymmetry is the mechanism this issue is built on, not an accident.
   MEASURED at 1440x900 as a Kurum Müdürü, th/td, before → after:
     /okullar             58/58 → 40/58
     /ogrenci             58/58 → 40/58
     /okullar/calisanlar  58/58 → 40/58

   `:not(.multiline-text)` — the three MultiLine grids are NOT governed by this.
   `MultiLine="true"` makes rc.4 replace the RowSize height with an inline
   `height: 100%` and tag the DATA cells (only) `multiline-text`, so those rows
   are content-sized on purpose: a two-line "Görev" cell must be allowed to grow
   and a one-line one must be allowed not to. Without the `:not()` this rule
   would out-specify their own floors — `table.fluent-data-grid td` is (0,1,2)
   against the (0,1,1) of a page-level `.fluent-data-grid td` — and quietly
   resize all three. MEASURED at 1440x900, unchanged across this change:
   /sms-gecmisi td 60px (its page-level floor), /gorevler/ata td 49px on a short
   row and 99px on a two-line one.

   Scope is app-wide and NOT keyed on `data-grid-fullwidth`: this replaces a
   CONSTRUCTOR-level default that applied to every grid, so scoping it to a
   class would silently shrink every grid that does not carry it. `table.`
   prefix per the house convention in this file — the library's own grid rules
   land AFTER app.css in source order (see the DATA GRID FULL WIDTH banner), so
   a tie loses here. Nothing in the library bundle sets `min-height` on `td`, so
   nothing competes with this today; the prefix is insurance, not a fix.

   Changing the number changes every list in the app. That is the point — it is
   one number in one place. Do NOT re-add `RowSize` to CocukDataGrid to change
   it; that is what put the header at 58px.
   =========================================================================== */
table.fluent-data-grid td:not(.multiline-text) {
    min-height: 58px;
}

/* ===========================================================================
   GRID EMPTY / LOADING ROW — breathing room for the two "there is nothing to
   show yet" rows, app-wide.

   rc.4 renders both of them itself, as a full-width cell inside the grid's
   <tbody>, and styles them with exactly one rule (verbatim from the package's
   Microsoft.FluentUI.AspNetCore.Components.bundle.scp.css, 5.0.0-rc.4-26180.1):

       .fluent-data-grid .empty-content-cell,
       .fluent-data-grid .loading-content-cell
           { font-weight: 600; text-align: center; height: 100%; user-select: none }

   No padding at all. MEASURED at 1440x900 on /ogrenci's archived grid before
   this rule: the empty cell was 1142 x 21 — a bold sliver hard against the
   header row, which is a large part of why "this page shows nothing when there
   is no data" was a believable bug report.

   Why it is HERE and not in the components' scoped stylesheets: this <td> is
   emitted by FluentDataGrid, so it carries no b-xxxxxxxxxx scope attribute and
   no .razor.css can reach it (DESIGN-GUIDELINES.md, "the scope attribute is
   never on the Fluent element"). A global rule is the only reachable place.

   24px here + 24px inside GridEmptyState / GridLoadingState = the 48px the
   hand-rolled empty-state cards used, and a text-only default (a grid with no
   <EmptyContent>, showing the localizer's "Kayıt bulunmuyor.") still clears the
   header instead of hugging it.

   Specificity note: the library's rule is (0,2,0) and lands AFTER app.css in
   source order (App.razor links AntikCocuk.V5.styles.css, which @imports the
   bundle, after app.css) — so a tie loses here. `table.` makes this (0,2,1) and
   wins outright. Same argument as the DATA GRID FULL WIDTH block above; do not
   "simplify" the selector.
   =========================================================================== */
table.fluent-data-grid .empty-content-cell,
table.fluent-data-grid .loading-content-cell {
    padding-block: 24px;
}

/* ===========================================================================
   VISUALLY HIDDEN — the standard screen-reader-only utility. NOT a FluentUI
   override: it touches nothing the library ships and is not keyed off any
   fluent-* element. It is the plain, decades-old clip recipe.

   What it is for: an element that must exist for assistive tech and for
   Routes.razor:25's <FocusOnNavigate Selector="h1" />, but that must not
   appear on screen. Today that is the <h1> on the two activation pages
   (WorkerActivationPage / ParentActivationPage): those are login-style pages
   with no visible page title, and inventing one would be new on-screen copy —
   a design change nobody asked for.

   Why it lives HERE and not in a .razor.css: it rides on plain authored HTML,
   so a scoped rule WOULD reach it (the b-xxxxx scope attribute lands on plain
   HTML, unlike a Class= passed to a Blazor component) — but two different
   pages need the same rule, and duplicating it is how the two copies drift.

   Why this recipe and not something shorter: `display: none` and
   `visibility: hidden` remove the element from the accessibility tree as well
   as from the screen, which defeats the entire purpose — a hidden <h1> that
   screen readers cannot see is just a missing <h1>. Clipping a 1x1 box keeps
   the element rendered and announceable. `clip` is the legacy form and
   `clip-path` the modern one; both are kept because they cost nothing and the
   pair is what every audited implementation of this utility ships.
   `white-space: nowrap` stops a long string from being wrapped into a tall
   column inside the 1px box, which some screen readers read one word per line.
   =========================================================================== */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}
