/*
 * Azur template — white cards floating on a pale sky page. The header and every
 * section sit in their own white panel with a thin #bae6fd edge, separated by
 * 14px of #f0f9ff tint. Shared by browser (edit) and mPDF (pdf). No flexbox, no
 * CSS grid, no transforms: tables / block layout only, so the two renderers
 * agree.
 *
 * THE CARD — the one construction every section reuses:
 *   table.cv-card   -> the panel's outer box, carrying only the 14px margin-top
 *                      that separates it from the card above.
 *   td.cv-card-cell -> the white background, the 1px #bae6fd border and the
 *                      18px interior padding.
 * The fill and the border live on the CELL, not on a div: mPDF paints a cell
 * background as ONE contiguous rect spanning the full cell, while a div's
 * background paints one rect per rendered text line. `border-collapse:
 * separate; border-spacing: 0` keeps the table exactly as tall as its cell —
 * `collapse` puts half the border outside the row box in the browser only,
 * which drifts the two renderers apart.
 *
 * NO page-break-inside:avoid ON A CARD, DELIBERATELY. That property is what
 * makes mPDF trial-render a block and rewind it onto a fresh page, and a table
 * cell BACKGROUND written during the trial is flushed onto the starting page
 * and left behind as a ghost rectangle (measured 2026-07-22 on soleil) — here
 * that would be a stray white panel on the pale page. A filled card doesn't
 * need it: a single-cell table that doesn't fit the space left on the page is
 * moved WHOLE to the next page by mPDF anyway (measured for the atrium build),
 * so its edge always closes on four sides. The avoid rules below sit on the
 * unfilled entry rows, where a rewind leaves nothing behind, and experience is
 * one card PER ENTRY (see azur.php's header) so no card is ever page-tall.
 *
 * EVERYTHING SITS INSIDE A <td>, so the whole in-td trap class applies and is
 * designed around here:
 *   - fonts are declared at td level (mPDF does not inherit font-family/size
 *     into cells — text silently falls back to the serif document default);
 *   - every bold is the KEYWORD `bold`, never a numeric 600/700 (mPDF ignores
 *     numeric weights);
 *   - every vertical gap inside a card is a nested table's own margin-top —
 *     block margins/paddings are dropped inside a cell;
 *   - the hairline under a section label is a nested table's td border-bottom,
 *     not the h2's own border-bottom (which shrinks to its text width in a
 *     cell);
 *   - bullets are two-cell tables (marker cell + text cell) because an li
 *     hanging indent is dropped in a cell, and the • is real HTML text — CSS
 *     generated content renders nothing at all in mPDF;
 *   - skills chips are a grid table of auto-width chip tables, never
 *     inline-blocks (consecutive ones merge into a single box in mPDF and their
 *     padding is dropped inside a cell) and never repeated floats (mPDF stacks
 *     those instead of packing them into rows).
 *
 * Palette: sky #0284c7 (labels, dates, dots), deep ink #0c4a6e (name, titles),
 * body #334155, meta #64748b, light meta #94a3b8, separators #7dd3fc, card edge
 * #bae6fd, page + chip tint #f0f9ff. Fixed in the CSS rather than driven by
 * settings.accentColor, so the card edges and the accents can never drift
 * apart; tpl_dots is passed the same #0284c7 explicitly.
 *
 * multipage:true — no fixed heights anywhere, no bottom padding on the page
 * (real trailing space opens a blank final page), and inter-card spacing is an
 * unconditional margin-TOP: a margin-bottom on a repeated block double-counts
 * in mPDF's pagination estimate, and mPDF drops `+` sibling rules entirely, so
 * neither the sibling-combinator nor the first-child-override form works here.
 *
 * Font stacks lead with a DejaVu face: mPDF substitutes Arial/Helvetica with
 * DejaVu *Condensed* (no bold face), so bold weights would silently export as
 * regular otherwise.
 */

/* The ONLY way to tint every sheet of a multipage export: a background on
   .resume-page paints just the flowed block, so page 2 would be white below
   where the content ends. Inert for browser screen rendering (so it never
   tints the builder chrome).
   The margins belong here too rather than being left to PdfService's zero
   page margins: that zero is exactly why the wrapper's padding-top — which
   lands on page 1 alone — was every later page's only top margin. `@page
   :first` zeroes the top margin so page 1 keeps using the wrapper padding and
   its output is unchanged; left/right stay 0 because the wrapper's horizontal
   padding already applies to every page. builder.js reads these values back
   out of CSSOM so its page-count model matches what mPDF actually does. */
@page {
    background-color: #f0f9ff;
    margin: 20px 0 20px 0;
}
@page :first {
    margin-top: 0;
}

.resume-page.resume-azur {
    width: 794px;                /* A4 @ 96dpi -> fills A4 width in mPDF */
    box-sizing: border-box;
    padding: 20px 30px 0;        /* zero bottom: trailing space opens a blank final page */
    background: #f0f9ff;
    color: #334155;
    font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif;
    font-size: 13.5px;
    line-height: 1.5;
}
/* mPDF does NOT inherit font-family/size into table cells — and in this
   template every single line of content is inside one, so this rule is what
   keeps the body out of the serif document default. No-op in the browser.
   Rules that override size/colour inside a specific cell are ordered after it. */
.resume-azur td {
    font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif;
    font-size: 13.5px;
    line-height: 1.5;
    color: #334155;
}

/* ---- the card ------------------------------------------------------------
 * margin-TOP only, unconditional, with no first-item override of any kind (see
 * the multipage note at the top of this file). The header card gets the same
 * 14px, on top of the page's own 20px padding. */
.resume-azur table.cv-card {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin-top: 14px;
    autosize: 1;                 /* mPDF-only; see the note below */
}
/* `autosize: 1` is mPDF's own CSS property (ignored by browsers, applied only
   to a top-level table) and it is what actually makes a card move whole to the
   next page. Measured on this template 2026-07-22: mPDF treats a ONE-ROW table
   as keep-together, and when it doesn't fit the space left on the page it first
   tries to SHRINK it — scaling the whole card's type down by up to the global
   shrink_tables_to_fit factor of 1.4 (Tag/Table.php, the `$tableheight >
   $remainingpage` branch) — and only breaks the page if even that isn't enough.
   The education card duly exported at 7.7pt against the rest of the CV's 10.1pt,
   crushed into the page foot. Capping the factor at 1 leaves mPDF no shrink to
   spend, so it adds the page instead. */
.resume-azur td.cv-card-cell {
    background: #ffffff;
    border: 1px solid #bae6fd;
    padding: 18px;
    vertical-align: top;
}
/* pdf mode: mPDF doesn't reliably honor :last-child, so the server marks
   whichever card renders last with this plain class instead. Unscoped on
   purpose — it applies to whichever element carries it. Belt-and-braces here,
   since spacing is margin-top only. */
.resume-azur .is-last {
    margin-bottom: 0;
}

/* ---- header card: circle portrait | identity -----------------------------
 * The portrait column is box-sized so its declared width means the same in both
 * renderers (mPDF measures a cell from its padding box, the browser from the
 * content box unless told otherwise): 115 - 20 right padding leaves 95px, the
 * portrait's exact size, so it never overflows or shifts the identity column. */
.resume-azur table.cv-head {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
}
.resume-azur td.cv-head-photo {
    width: 115px;
    box-sizing: border-box;
    padding: 0 20px 0 0;
    vertical-align: top;
}
.resume-azur td.cv-head-id {
    vertical-align: middle;
    padding: 0;
}
/* No width/height here: tpl_photo emits both inline, and the pdf-mode initials
   fallback is a GD PNG (a true circle), which keeps its geometry inside a cell
   where a styled div would collapse to a small square. */
.resume-azur .cv-photo,
.resume-azur .cv-photo-initials {
    display: block;
}
/* Identity lines are ROWS of a nested table, not margin-stacked blocks: mPDF
   drops block margins inside a cell, so the vertical rhythm is td padding. */
.resume-azur table.cv-id {
    width: 100%;
    border-collapse: collapse;
}
.resume-azur table.cv-id td {
    padding: 0;
}
.resume-azur td.cv-id-title {
    padding-top: 7px;
}
.resume-azur td.cv-id-contact {
    padding-top: 10px;
}
.resume-azur .cv-name {
    font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif;
    font-size: 26px;
    font-weight: bold;
    color: #0c4a6e;
    letter-spacing: -0.2px;
    line-height: 1.15;
    margin: 0;
}
.resume-azur .cv-jobtitle {
    font-size: 11.5px;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 2px;
    color: #0284c7;
}
.resume-azur .cv-contact {
    font-size: 11.5px;
    color: #64748b;
    line-height: 1.6;
}
.resume-azur .cv-contact-sep {
    color: #7dd3fc;
}

/* ---- section label at the top of a card ----------------------------------
 * The hairline is the nested cell's border-bottom: an h2's own border-bottom
 * shrinks to its text width inside a table cell. */
.resume-azur table.cv-sec-row {
    width: 100%;
    border-collapse: collapse;
    margin: 0;
}
.resume-azur table.cv-sec-row td {
    border-bottom: 1px solid #e0f2fe;
    padding: 0 0 6px;
}
.resume-azur .cv-sec-title {
    font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif;
    font-size: 13px;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 1.6px;
    color: #0284c7;
    border: none;
    margin: 0;
    padding: 0;
    page-break-after: avoid;
}

/* ---- entries inside a card -----------------------------------------------
 * Two-cell "content left / date right" rows. A table and not a float: a float
 * inside a block mPDF may have to move makes it miscalculate the block height
 * and duplicate content. The avoid lives here rather than on the card because
 * these rows carry no fill — a rewound block that had one would ghost its
 * rectangle onto the page it started on. */
.resume-azur table.cv-entry {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
    margin-top: 11px;
    page-break-inside: avoid;
}
.resume-azur td.cv-entry-main {
    padding: 0;
    vertical-align: top;
    text-align: left;
}
/* No white-space:nowrap: a spelled-out French range ("septembre 2021 – juin
   2024") is wider than this column, and one nowrap cell shrinks the WHOLE
   layout table in mPDF (graphite, 2026-07). It wraps to a second right-aligned
   line instead. */
.resume-azur td.cv-entry-side {
    width: 150px;
    padding: 0 0 0 14px;
    vertical-align: top;
    text-align: right;
}
/* Full-width follow-on rows inside a card (the summary paragraph, the chip
   list, an entry's details line). Their only job is to carry the gap a block
   margin cannot. */
.resume-azur table.cv-text-row,
.resume-azur table.cv-sub-row {
    width: 100%;
    border-collapse: collapse;
}
.resume-azur table.cv-text-row {
    margin-top: 10px;
}
.resume-azur table.cv-sub-row {
    margin-top: 4px;
}
.resume-azur table.cv-text-row td,
.resume-azur table.cv-sub-row td {
    padding: 0;
}
.resume-azur .cv-item-title {
    font-weight: bold;
    color: #0c4a6e;
}
.resume-azur .cv-item-org {
    color: #334155;
}
.resume-azur .cv-item-field {
    color: #64748b;
}
.resume-azur .cv-item-sep {
    color: #7dd3fc;
}
/* edit mode only: a separator that must read as glued to the preceding editable
   text (the education comma) can't be nested inside it — anything inside an
   editable becomes stored user data — so it sits on its own source line and
   pulls back over that newline's rendered space. The pdf branch emits the same
   comma with no whitespace at all and never uses this class. */
.resume-azur .cv-sep-tight {
    margin-left: -4px;
}
.resume-azur .cv-dates {
    font-size: 11.5px;
    letter-spacing: 0.2px;
    color: #0284c7;
}
.resume-azur .cv-item-loc {
    font-size: 11px;
    color: #94a3b8;
}
.resume-azur .cv-item-details {
    font-size: 12.5px;
    color: #64748b;
}
/* Ragged-right, never justify (mPDF spacing artifacts). */
.resume-azur .cv-summary {
    text-align: left;
    color: #334155;
}

/* Bullets: a two-cell table each — a real hanging indent that survives inside a
   cell, where an li's own indent is dropped. The marker is real HTML text; a
   CSS content: marker renders nothing at all in mPDF. */
.resume-azur table.cv-bullet {
    width: 100%;
    border-collapse: collapse;
    margin-top: 4px;
}
.resume-azur td.cv-bullet-mk {
    width: 14px;
    padding: 0;
    vertical-align: top;
    color: #38bdf8;
    font-size: 13px;
    line-height: 20px;           /* centers the dot on the first 13px/1.5 text line */
}
.resume-azur td.cv-bullet-tx {
    position: relative;
    padding: 0;
    vertical-align: top;
    font-size: 13px;
    color: #334155;
}

/* ---- skills chips --------------------------------------------------------
 * A real grid table (one row per three chips) holding one AUTO-WIDTH chip table
 * per cell. Not inline-blocks: consecutive ones merge into a single undivided
 * box in mPDF and their padding is dropped inside a cell. Not floats: repeated
 * same-direction floats stack in mPDF instead of packing into rows. The gap
 * between chips is the grid cell's own padding, since border-spacing would also
 * inset the grid from the card's edges. */
.resume-azur table.cv-chip-grid {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
    margin-top: 10px;
}
.resume-azur td.cv-chip-cell {
    width: 33.33%;
    vertical-align: top;
    padding: 0 8px 6px 0;
}
.resume-azur table.cv-chip {
    border-collapse: collapse;
}
.resume-azur .cv-chip td {
    background: #f0f9ff;
    border: 1px solid #bae6fd;
    color: #075985;
    padding: 4px 10px;
    font-size: 12px;
    line-height: 1.45;
}

/* ---- languages schedule (name / level) -----------------------------------
 * ONE multi-row table, never a table per line: repeated small tables inflate
 * mPDF's own pagination height enough to cost a whole page (cobalt, 2026-07). */
.resume-azur table.cv-list {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
    margin-top: 10px;
}
.resume-azur td.cv-list-k {
    position: relative;
    width: 200px;
    padding: 0 14px 4px 0;
    vertical-align: top;
    font-size: 13px;
    font-weight: bold;
    color: #0c4a6e;
}
.resume-azur td.cv-list-v {
    padding: 0 0 4px;
    vertical-align: top;
    font-size: 13px;
    color: #64748b;
}
/* The level slot holds EITHER dot glyphs or free text (tpl_dots passes text
   through untouched), so the tracking that spaces the dots apart lives on the
   dots themselves — otherwise a written level like "C1 — courant" exports as
   letterspaced small type. */
.resume-azur .cv-dot {
    font-size: 10px;
    letter-spacing: 1px;
}
.resume-azur .cv-dot-on {
    color: #0284c7;
}
.resume-azur .cv-dot-off {
    color: #cbd5e1;
}

/* =====================================================================
 * Edit-mode affordances (browser only — these elements are never emitted in
 * pdf mode, so none of this reaches mPDF).
 * Every [contenteditable]/[data-ph] rule stays at ONE level below the page
 * class: mPDF can't parse those chunks and applies the declaration to a
 * two-or-more-level prefix instead, repainting whatever pdf-mode element that
 * prefix names (confirmed on graphite, 2026-07).
 * ===================================================================== */

.resume-azur [contenteditable][data-ph]:empty:before {
    content: attr(data-ph);
    color: #b6c6d4;
    font-style: italic;
    pointer-events: none;
}
.resume-azur [contenteditable] {
    outline: none;
    transition: box-shadow 0.12s ease, background 0.12s ease;
}
.resume-azur [contenteditable]:hover {
    box-shadow: 0 0 0 1px #bae6fd;
}
.resume-azur [contenteditable]:focus {
    box-shadow: 0 0 0 2px #0284c7;
    background: #f0f9ff;
}
/* Edit-mode contact fields carry their own class rather than being selected
   through [contenteditable] (see the note above), and their spacing replaces
   the middots the pdf branch joins the filled fields with — an always-present
   empty slot must not print a separator beside it. */
.resume-azur .cv-contact-f {
    display: inline-block;
    min-width: 40px;
    margin-right: 12px;
}

.resume-azur .cv-item {
    position: relative;
}
.resume-azur .edit-controls {
    position: absolute;
    top: -2px;
    right: -44px;
    opacity: 0;
    transition: opacity 0.12s ease;
    white-space: nowrap;
    z-index: 5;
}
.resume-azur .edit-controls--inline {
    position: absolute;
    left: -26px;
    right: auto;
    top: 0;
}
.resume-azur .cv-item:hover > .edit-controls,
.resume-azur .cv-list-k:hover > .edit-controls,
.resume-azur .cv-bullet-tx:hover > .edit-controls,
.resume-azur .edit-controls:hover {
    opacity: 1;
}
.resume-azur .edit-controls button {
    font-family: inherit;
    font-size: 13px;
    line-height: 1;
    width: 20px;
    height: 20px;
    margin-left: 2px;
    padding: 0;
    border: 1px solid #bae6fd;
    background: #ffffff;
    color: #0284c7;
    border-radius: 3px;
    cursor: pointer;
}
.resume-azur .edit-controls button:hover {
    background: #0284c7;
    border-color: #0284c7;
    color: #ffffff;
}

/* Browser-only chip form, matching the pdf-mode chip tables: same tint, same
   edge, same type size. */
.resume-azur .cv-chip-list {
    font-size: 12px;
}
.resume-azur .cv-chip-edit {
    display: inline-block;
    margin: 0 6px 6px 0;
    padding: 4px 10px;
    border: 1px solid #bae6fd;
    background: #f0f9ff;
    color: #075985;
    font-size: 12px;
    white-space: nowrap;
}

.resume-azur .cv-add {
    font-family: inherit;
    font-size: 12.5px;
    margin-top: 10px;
    padding: 4px 10px;
    border: 1px dashed #bae6fd;
    background: #ffffff;
    color: #0284c7;
    border-radius: 3px;
    cursor: pointer;
}
.resume-azur .cv-add:hover {
    background: #f0f9ff;
    border-color: #0284c7;
}
.resume-azur .cv-add--sm {
    font-size: 11.5px;
    padding: 2px 8px;
}

.resume-azur .cv-current {
    display: block;
    font-family: inherit;
    font-size: 11px;
    font-weight: normal;
    color: #94a3b8;
    margin-top: 2px;
    white-space: nowrap;
    cursor: pointer;
}
.resume-azur .cv-current input {
    vertical-align: middle;
}

.resume-azur .cv-chip-x {
    font-family: inherit;
    border: none;
    background: none;
    color: #b00;
    cursor: pointer;
    padding: 0 0 0 3px;
    opacity: 0;
    font-size: 13px;
}
.resume-azur .cv-chip-edit:hover .cv-chip-x {
    opacity: 1;
}

.resume-azur .cv-dot-btn,
.resume-azur .cv-level-toggle {
    font-family: inherit;
    border: none;
    background: none;
    padding: 0 1px;
    cursor: pointer;
    font-size: 10px;
}
.resume-azur .cv-dot-btn.cv-dot-on {
    color: #0284c7;
}
.resume-azur .cv-dot-btn.cv-dot-off {
    color: #cbd5e1;
}
.resume-azur .cv-level-toggle {
    font-size: 9px;
    color: #94a3b8;
    margin-left: 4px;
    opacity: 0;
    transition: opacity 0.12s ease;
}
.resume-azur .cv-chip-edit:hover .cv-level-toggle,
.resume-azur .cv-list-v:hover .cv-level-toggle {
    opacity: 1;
}
