/* Self-contained colors (not relying on Gin CSS custom properties, which don't reliably resolve on this route) + explicit dark-mode overrides, since Gin's dark mode (html.gin--dark-mode) is enabled by default here. */ #figli-home-app { --figli-bg: #ffffff; --figli-bg-alt: #f5f6f8; --figli-text: #1a1a1a; --figli-text-light: #6b7280; --figli-border: #dcdee2; --figli-error: #c9312b; --figli-positive: #1a7f37; --figli-warning: #b8860b; --figli-col-hover: rgba(15, 23, 42, 0.05); font-family: Inter, -apple-system, sans-serif; /* Bottom cut to a third (top left alone) -- with the outer page scroll already eliminated (see hide-admin-chrome.css's main.page- content override), the full 1rem below the table was just dead space past the last visible row. */ margin: 1rem 0 0.33rem; color: var(--figli-text); } html.gin--dark-mode #figli-home-app { --figli-bg: #232426; --figli-bg-alt: #2c2d30; --figli-text: #e8e9ea; --figli-text-light: #a1a5ab; --figli-border: #3d3e42; --figli-error: #ff6b6b; --figli-positive: #4ade80; --figli-warning: #f0b429; --figli-col-hover: rgba(255, 255, 255, 0.07); } #figli-home-app .figli-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.25rem; margin-bottom: 1rem; padding: 0.75rem 1rem; background: var(--figli-bg-alt); border: 1px solid var(--figli-border); border-radius: 6px; color: var(--figli-text); } #figli-home-app .figli-toolbar label { display: flex; flex-direction: column; font-size: 0.75rem; font-weight: 600; color: var(--figli-text-light); gap: 0.15rem; } #figli-home-app .figli-toolbar select { font-size: 0.85rem; padding: 0.2rem 0.4rem; background: var(--figli-bg); color: var(--figli-text); border: 1px solid var(--figli-border); border-radius: 4px; } /* Each filter control + its "✕ effacer" button, side by side. */ #figli-home-app .figli-filter-row { display: flex; align-items: center; gap: 0.25rem; } #figli-home-app .figli-filter-clear { background: transparent; border: none; color: var(--figli-text-light); cursor: pointer; font-size: 0.8rem; line-height: 1; padding: 0.15rem; } #figli-home-app .figli-filter-clear:hover { color: var(--figli-error); } /* Compte/Type filters: a native in place (figli-type-select below), no modal needed for this one field. */ #figli-home-app .figli-badge-editable { cursor: pointer; border: 1px solid transparent; } #figli-home-app .figli-badge-editable:hover { border-color: currentColor; } #figli-home-app .figli-type-select { font-size: 0.72rem; padding: 0.05rem 0.2rem; background: var(--figli-bg); color: var(--figli-text); border: 1px solid var(--figli-border); border-radius: 4px; } /* Client/Facture/Libellé: click-to-edit like the type badge above, but plain text rather than a pill -- a dotted underline is enough of an affordance without implying a fixed set of choices the way the type badge's pill shape does. */ /* display: block + min-height (not just the default inline text-only box) so the whole cell is a forgiving click target even when empty -- the "—" placeholder alone is a tiny, easy-to-miss target otherwise. */ #figli-home-app .figli-editable-cell { display: block; min-height: 1.2em; cursor: pointer; border-bottom: 1px dotted transparent; } #figli-home-app .figli-editable-cell:hover { border-bottom-color: var(--figli-text-light); } #figli-home-app .figli-inline-input { font-size: 0.8rem; padding: 0.1rem 0.3rem; background: var(--figli-bg); color: var(--figli-text); border: 1px solid var(--figli-border); border-radius: 4px; width: 100%; box-sizing: border-box; } #figli-home-app .figli-note { color: var(--figli-text-light); font-weight: 400; font-size: 0.75rem; } /* One column per icon (link, edit) rather than one shared cell -- with a shared cell, text-align: center puts a lone button (rows with no link icon) in a different spot than a row with both, so the edit pencil never lined up from row to row. Separate columns line up by construction, and get a tight, icon-sized width instead of the table's default 0.6rem horizontal cell padding. */ #figli-home-app td.actions-col, #figli-home-app th.actions-col { width: 3%; padding: 0.2rem 0.1rem; text-align: center; white-space: nowrap; } /* Column widths for the fixed layout above -- sized so the widest realistic content (longest client/type label, an 8-figure amount) fits without pushing the table past 100%, while the two free-text columns (Client, Libellé/Détail) get most of the remaining room. Every column is a percentage (including actions-col/Date above, deliberately not rem) -- mixing units meant the rem columns' pixel width was added *on top of* the percentage budget instead of coming out of it, silently pushing the table a few pixels past 100% and reintroducing the horizontal scrollbar this is meant to avoid. Percentages intentionally sum to a little under 100%: table-layout: fixed treats them as relative weights, not a hard budget, so slightly under leaves headroom rather than risking every column getting scaled down to fit. */ #figli-home-app th:nth-child(2), #figli-home-app td:nth-child(2) { width: 5%; white-space: nowrap; } #figli-home-app th:nth-child(3), #figli-home-app td:nth-child(3) { width: 10%; } #figli-home-app th:nth-child(4), #figli-home-app td:nth-child(4) { width: 7%; } #figli-home-app th:nth-child(5), #figli-home-app td:nth-child(5) { width: 5%; white-space: nowrap; } #figli-home-app .amount:not(.compte-col) { width: 6.2%; white-space: nowrap; } /* HT/TTC narrower than the general .amount rule above (still used by Écart) -- shorter header text (HT/TTC vs. the old Montant HT/Montant TTC) and TVA splitting the row between them means neither needs as much room. TVA itself narrower still: "12,64 %" is the longest realistic value (see figli_compta_ledger_update_8005()'s docblock on backfilled non-round rates), well short of an 8-figure amount. `.amount` doubled up in the selector (not just .figli-ht-col alone): :not(.compte-col) in the rule above counts toward specificity same as a real class, so a single-class selector here would lose to it. */ #figli-home-app .amount.figli-ht-col, #figli-home-app .amount.figli-ttc-col { width: 5%; } /* Cotisation diffuseur URSSAF (1,1%) -- blank for every non-"Entrée client" row (see figli_compta_ledger_node_presave()), same width budget as HT/TTC since it's a real € amount, not a short rate like TVA. */ #figli-home-app .amount.figli-cotisation-col { width: 5%; } #figli-home-app .amount.figli-tva-col { width: 3.5%; } /* Non-official TVA rate marker -- a thick red underline on the cell itself rather than a small badge/dot (tried first, not visible enough): the column is only ~3.5% wide, barely enough for "12,64 %" itself, so a border under the whole cell reads clearly at a glance without needing extra horizontal room a text/icon badge would need. Tooltip (title attribute in the twig template) carries the actual explanation. */ #figli-home-app td.figli-tva-nonofficial { border-bottom: 3px solid var(--figli-error); } #figli-home-app .amount.compte-col { width: 4.3%; white-space: nowrap; } /* Buttons stay inline (not flex) inside the -- display: flex on a table cell breaks the table's own column-width calculation (observed: a ~55px gap opening up between this column and the next, and the buttons rendering outside their cell's actual boundary). */ #figli-home-app .figli-edit-btn { display: inline-flex; align-items: center; justify-content: center; width: 1.4rem; height: 1.4rem; padding: 0; background: transparent; border: 1px solid transparent; border-radius: 4px; color: var(--figli-text-light); cursor: pointer; vertical-align: middle; } #figli-home-app .figli-edit-btn:hover { background: var(--figli-bg-alt); border-color: var(--figli-border); color: var(--figli-text); } /* Reconciliation badge on entrée rows: répartition (money owed) vs the combined répartition of every linked sortie (money actually paid out). */ #figli-home-app .figli-recon-badge { display: inline-block; margin-left: 0.4rem; padding: 0.05rem 0.4rem; border-radius: 10px; font-size: 0.68rem; font-weight: 600; white-space: nowrap; background: #1a7f371a; color: var(--figli-positive); } /* Not every badge using this class does something on click (the ouverture/clôture écart badge is purely informational) -- only show the pointer cursor where a click actually goes somewhere. */ #figli-home-app .figli-recon-badge.is-clickable { cursor: pointer; } /* Still green, not orange -- it's money owed, not a warning, and green-but-darker reads as "related to, but not yet, Lié" (the default badge green above) rather than as an unrelated anomaly color. */ #figli-home-app .figli-recon-badge.is-reste { background: #1665341a; color: #166534; } #figli-home-app .figli-recon-badge.is-anomalie { background: #c9312b1a; color: var(--figli-error); } #figli-home-app .figli-clear-drilldown { font-size: 0.8rem; padding: 0.2rem 0.6rem; } /* Entrée + sorties liées drill-down: a modal overlay rather than replacing the main table's rows in place, so opening/closing it never disturbs the main table's scroll position. */ #figli-home-app .figli-modal-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 100; } #figli-home-app .figli-modal { background: var(--figli-bg); color: var(--figli-text); border: 1px solid var(--figli-border); border-radius: 8px; width: 96vw; max-height: 85vh; display: flex; flex-direction: column; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3); } #figli-home-app .figli-modal-header { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem 1rem; border-bottom: 1px solid var(--figli-border); } #figli-home-app .figli-modal-header h3 { margin: 0; font-size: 0.95rem; font-weight: 700; } #figli-home-app .figli-modal-close { background: transparent; border: 1px solid transparent; border-radius: 4px; color: var(--figli-text-light); cursor: pointer; font-size: 0.9rem; padding: 0.15rem 0.45rem; } #figli-home-app .figli-modal-close:hover { background: var(--figli-bg-alt); border-color: var(--figli-border); color: var(--figli-text); } /* Signalement modal -- much smaller than the entrées/sorties drill-down above (a short list of tags, not a table), so it gets its own narrow width instead of the 96vw default. */ #figli-home-app .figli-flag-modal { width: 24rem; max-width: 90vw; } #figli-home-app .figli-flag-modal-body { padding: 0.75rem 1rem 1rem; } #figli-home-app .figli-flag-modal-row { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.35rem 0; border-bottom: 1px solid var(--figli-border); } #figli-home-app .figli-flag-remove { background: transparent; border: 1px solid transparent; border-radius: 4px; color: var(--figli-text-light); cursor: pointer; font-size: 0.8rem; padding: 0.1rem 0.4rem; flex: none; } #figli-home-app .figli-flag-remove:hover { background: var(--figli-bg-alt); border-color: var(--figli-border); color: var(--figli-error); } #figli-home-app .figli-flag-modal-add { display: flex; gap: 0.5rem; margin-top: 0.75rem; } #figli-home-app .figli-flag-modal-add input { flex: 1; font-size: 0.85rem; padding: 0.3rem 0.5rem; border: 1px solid var(--figli-border); border-radius: 4px; background: var(--figli-bg); color: var(--figli-text); } #figli-home-app .figli-modal-body { overflow-y: auto; overflow-x: hidden; padding: 0; } #figli-home-app .figli-modal-body table { font-size: 0.8rem; table-layout: fixed; width: 100%; /* Only a handful of rows in this view -- wrap instead of the main table's nowrap, so 14 columns fit the modal width without ever needing horizontal scroll. */ white-space: normal; } #figli-home-app .figli-modal-body thead th { position: sticky; top: 0; } /* table-layout: fixed otherwise spreads all 16 columns evenly, squeezing the libellé text into the same width as an empty compte column -- give the columns that actually carry content (client/type/libellé) proportionally more room, comptes/montants less. */ #figli-home-app .figli-modal-body th:nth-child(1), #figli-home-app .figli-modal-body td:nth-child(1) { width: 2rem; } #figli-home-app .figli-modal-body th:nth-child(2), #figli-home-app .figli-modal-body td:nth-child(2) { width: 4.5rem; } #figli-home-app .figli-modal-body th:nth-child(3), #figli-home-app .figli-modal-body td:nth-child(3) { width: 9%; } #figli-home-app .figli-modal-body th:nth-child(4), #figli-home-app .figli-modal-body td:nth-child(4) { width: 8%; } #figli-home-app .figli-modal-body th:nth-child(5), #figli-home-app .figli-modal-body td.figli-libelle { width: 24%; min-width: 0; max-width: none; } #figli-home-app .figli-modal-body .amount.compte-col { width: 4.5%; } #figli-home-app .figli-modal-body .amount:not(.compte-col) { width: 7%; } /* Sliding-window edge markers (IntersectionObserver targets) -- kept short so they don't add visible dead space when idle, tall enough (min-height) to reliably intersect the observer's root margin. */ #figli-home-app tr.figli-sentinel-row td { padding: 0.3rem 0.6rem; min-height: 1.5rem; text-align: center; color: var(--figli-text-light); font-size: 0.75rem; font-style: italic; } #figli-home-app .figli-error { background: #fde8e8; border: 1px solid #f4a3a3; color: #7a1a1a; padding: 0.75rem 1rem; border-radius: 6px; } /* Dismissible, doesn't replace the table like the top-level fetch error does -- a failed inline type change is a small hiccup, not a reason to hide everything that's already loaded. */ #figli-home-app .figli-inline-error { margin-bottom: 1rem; display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }